最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 详解Promise 和 setTimeout速度比拼

    正文概述 掘金(Liysuo)   2021-02-26   605

    实验

    先做一个实验:来看看立即解决的 Promise 和立即超时( 0 毫秒的超时)哪个执行的更快?

    Promise.resolve(1).then(function resolve() {
      console.log('Resolved!');
    });
    
    setTimeout(function timeout() {
      console.log('Timed out!');
    }, 0);
    
    // logs 'Resolved!'
    // logs 'Timed out!'
    

    Promise.resolve(1) 是一个静态函数,可返回立即解决的 promise。 setTimeout(callback, 0) 执行延迟为 0 毫秒的回调。
    打开执行并检查控制台。您会看到日志先打印了 'Resolved!' ,然后打印了 'Timeout completed!'。立即解决的承诺比立即超时处理得更快。
    是因为 Promise.resolve(true).then(...) 在 setTimeout(..., 0) 之前被调用了,所以 promise 的处理过程会更快吗?
    那我们就修改一下实验条件,先调用 setTimeout(...,0):

    setTimeout(function timeout() {
      console.log('Timed out!');
    }, 0);
    
    Promise.resolve(1).then(function resolve() {
      console.log('Resolved!');
    });
    
    // logs 'Resolved!'
    // logs 'Timed out!'
    

    执行并查看控制台,结果是一样的!
    尽管 setTimeout(..., 0) 在 Promise.resolve(true).then(...) 之前被调用了,但是 'Resolved!' 仍然在 'Timed out!' 之前被输出。
    实验表明,立即解决的 promise 在立即超时之前已得到处理。所以。。。这是为什么?

    事件循环

    与异步 JavaScript 有关的问题可以通过探索事件循环解答答。先回顾一下异步 JavaScript 的工作原理。详解Promise 和 setTimeout速度比拼 调用栈(call stack) 是 LIFO(后进先出)的结构,用于存储在代码执行期间创建的执行上下文。简而言之,调用栈执行用来函数。
    Web API 是异步操作(fetch 请求、promises、计时器),回调等待这里的工作完成。
    **任务队列(task queue)**是一个 FIFO(先进先出)的结构,其中包含准备好执行的异步操作的回调。例如,超时的 setTimeout() 的回调(准备执行)进入任务队列中。
    工作队列(job queue) 是一个 FIFO(先进先出)的结构,其中包含准备执行的 promise 的回调。例如,已解决的 resolve 或拒绝回调进入工作队列中。
    最后,事件循环(event loop) 会一直监视调用栈是否为空。如果调用栈为空,则事件循环会查找工作队列或任务队列,并使准备好执行的回调出队到调用栈中。

    工作队列与任务队列

    下面从事件循环的角度来看一下前面的实验。我会逐步分析代码的执行情况。

    • 1、调用堆栈执行 setTimeout(..., 0) 并“安排”一个计时器。 timeout() 回调存储在 Web API 中:
    setTimeout(function timeout() {  console.log('Timed out!');}, 0);
    Promise.resolve(1).then(function resolve() {
      console.log('Resolved!');
    });
    

    详解Promise 和 setTimeout速度比拼

    • 2、调用栈执行 Promise.resolve(true).then(resolve) 并“安排”一个 promise 解析。 resolved() 回调存储在 Web API 中:
    setTimeout(function timeout() {
      console.log('Timed out!');
    }, 0);
    
    Promise.resolve(1).then(function resolve() {  console.log('Resolved!');});
    

    详解Promise 和 setTimeout速度比拼

    • 3、promise 立即解决,计时器立即超时。这时计时器回调 timeout() 被“排队”到任务队列,promise 回调 resolve() 被“排队”到工作队列:

    详解Promise 和 setTimeout速度比拼

    • 4、这里是最有意思部分:事件循环优先级使工作排在任务之上。事件循环使 promise 回调 resolve() 从工作队列中出队,并将其放入调用栈中,然后调用栈执行 promise 回调 resolve():
    setTimeout(function timeout() {
      console.log('Timed out!');
    }, 0);
    
    Promise.resolve(1).then(function resolve() {
      console.log('Resolved!');});
    

    详解Promise 和 setTimeout速度比拼

    • 5、最后,事件循环把计时器回调 timeout() 从任务队列中移出到调用栈中。然后调用栈执行计时器回调timeout():
    setTimeout(function timeout() {
      console.log('Timed out!');}, 0);
    
    Promise.resolve(1).then(function resolve() {
      console.log('Resolved!');
    });
    

    详解Promise 和 setTimeout速度比拼

    总结

    为什么立即解决的 promise 比立即计时器处理得更快?


    起源地下载网 » 详解Promise 和 setTimeout速度比拼

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元