栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

异步函数不返回值,但是console.log()可以:怎么办?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

异步函数不返回值,但是console.log()可以:怎么办?

您用Javascript编写的代码在一个线程上运行,这意味着,如果您的代码实际上可以等待某件事,它将阻止您的其他任何代码被执行。

在浏览器中阻止代码的一个很好的例子是

alert("cannotdoanythinguntilyouclickok");
。alert阻止了所有内容,用户甚至无法滚动或单击页面中的任何内容,并且您的代码也被阻止执行。

Promise.resolve(22).then(x=>alert("blocking")||"Hello World").then(  x=>console.log(    "does not resolve untill you click ok on the alert:",    x  ));

在控制台中运行它,您会明白我所说的阻塞。

当您想做一些需要时间的事情时,这会造成问题。在其他框架中,您将使用线程或进程,但是Javascript中没有这样的东西(从技术上讲,是在Web
worker和fork in node中存在的,但这是另一回事了,通常比使用异步api复杂得多)。

因此,当您要发出http请求时,可以使用,

fetch
但fetch需要一些时间才能完成,并且您的函数不应阻塞(必须尽快返回)。这就是为什么访存返回承诺的原因。

请注意,抓取操作是由浏览器/节点实现的,并且确实在另一个线程中运行,只有您编写的代码在一个线程中运行,因此可以保证,仅运行您编写的代码不会加快任何速度,但并行调用本机异步api会加快速度。

在promise之前,异步代码使用了回调或将返回可观察对象(例如XmlHttpRequest),但让我们讨论一下promise,因为您仍然可以将更传统的代码转换为promise。

Promise是一个具有

then
功能的对象(以及一堆当时是糖的东西,但功能相同),该功能带有2个参数。

  1. 解析处理程序:当承诺解析(没有错误并且完成)时,由承诺调用的函数。该函数将被传递一个带有resolve值的参数(对于http请求,这通常是响应)。
  2. 拒绝处理程序:当诺言被拒绝(有错误)时,诺言将调用的函数。此函数将传递一个参数,通常是错误或拒绝原因(可以是字符串,数字或其他任何东西)。

将回调转换为Promise。

传统的api(尤其是nodejs api)使用回调:

traditionalApi(  arg  ,function callback(err,value){     err ? handleFail(err) : processValue(value);  });

这使程序员难以捕捉错误或以线性方式(从上到下)处理返回值。尝试与错误处理并行执行或限制并行处理(不可能读取)变得更加不可能。

您可以将传统的api转换为promise

new Promise

const apiAsPromise = arg =>  new Promise(    (resolve,reject)=>      traditionalApi(        arg,        (err,val) => (err) ? reject(err) : resolve(val)      )  )

异步等待

这就是诺言的语法糖。它使承诺承诺功能看起来更传统,更易于阅读。那就是如果您想编写传统代码,我会认为编写小型函数更容易阅读。例如,您能猜出这是什么吗?:

const handleSearch = search =>  compose([    showLoading,    makeSearchRequest,    processRespose,    hideLoading  ])(search)  .then(    undefined,//don't care about the resolve    compose([      showError,      hideLoading    ])  );

Anayway;足够的咆哮。重要的部分是要了解

asyncawait
实际上并没有启动另一个线程,
async
函数总是返回一个Promise,
await
并且实际上没有阻塞或等待。它的语法糖
someFn().then(result=>...,error=>...)
,看起来像:

async someMethod = () =>  //syntax sugar for:  //return someFn().then(result=>...,error=>...)  try{    const result = await someFn();    ...   }catch(error){     ...   }}

这些示例始终显示,

try catch
但您不需要这样做,例如:

var alwaysReject = async () => { throw "Always returns rejected promise"; };alwaysReject().then(  x=>console.log("never happens, doesn't resolve")  ,err=>console.warn("got rejected:",err));

抛出的任何错误或

await
返回被拒绝的承诺都会导致异步函数返回被拒绝的承诺(除非您尝试抓住它)。很多时候,希望让它失败并让调用者处理错误。

当您希望诺言成功而被拒绝的诺言具有特殊值时,可能会需要捕获错误,以便您可以稍后进行处理,但是诺言在技术上不会拒绝,因此始终可以解决。

一个例子是

Promise.all
,它接受一个promise数组并返回一个新的promise,该promise解析为一个解析值数组,
或者在其中任何一个拒绝时都拒绝 。您可能只想获取所有承诺的结果并过滤掉被拒绝的承诺:

const Fail = function(details){this.details=details;},isFail = item => (item && item.constructor)===Fail;Promise.all(  urls.map(//map array of urls to array of promises that don't reject    url =>      fetch(url)      .then(        undefined,//do not handle resolve yet        //when you handle the reject this ".then" will return        //  a promise that RESOLVES to the value returned below (new Fail([url,err]))        err=>new Fail([url,err])      )  )).then(  responses => {    console.log("failed requests:");    console.log(      responses.filter(//only Fail type        isFail      )    );    console.log("resolved requests:");    console.log(      responses.filter(//anything not Fail type        response=>!isFail(response)      )    );  });


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/369751.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号