您好,登录后才能下订单哦!
小编给大家分享一下Promise比setTimeout()快的原因有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
为什么 Promise 比setTimeout() 快?
我们来做个实验。哪个执行得更快:立即解决的 Promise 还是立即setTimeout
(也就是0毫秒的setTimeout)?
Promise.resolve(1).then(function resolve() { console.log('Resolved!'); }); setTimeout(function timeout() { console.log('Timed out!'); }, 0); // 'Resolved!' // 'Timed out!'
promise.resolve(1)
是一个静态函数,它返回一个立即解析的promise
。setTimeout(callback, 0)
以0毫秒
的延迟执行回调函数。
我们可以看到先打印'Resolved!'
,再打印Timeout completed!
,立即解决的 promise 比立即setTimeout
更快。
是因为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!'); }); // 'Resolved!' // 'Timed out!'
setTimeout(..., 0)
在Promise.resolve(true).then(...)
之前被调用。但,还是先打印Resolved!
在打印'Timed out!'
。
这是为啥呢?
与异步 JS 相关的问题可以通过研究事件循环来回答。我们回顾一下异步 JS 工作方式的主要组成部分。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lt9zVHTf-1611275604640)(/img/bVcMQaI)]
调用堆栈是一个LIFO(后进先出)结构,它存储在代码执行期间创建的执行上下文。简单地说,调用堆栈执行这些函数。
Web api是异步操作(fetch 请求、promise、计时器)及其回调等待完成的地方。
**task queue (任务队列)是一个FIFO(先进先出)**结构,它保存准备执行的异步操作的回调。例如,超时的setTimeout()
的回调函数或准备执行的单击按钮事件处理程序都在任务队列中排队。
**job queue (作业队列)**是一个FIFO(先入先出)结构,它保存准备执行的promise
的回调。例如,已完成的承诺的resolve
或reject
回调被排在作业队列中。
最后,事件循环永久监听调用堆栈是否为空。如果调用堆栈为空,则事件循环查看作业队列或任务队列,并将准备执行的任何回调分派到调用堆栈中。
我们从事件循环的角度来看这个实验,我将对代码执行进行一步一步的分析。
A)调用堆栈执行setTimeout(..., 0)
并计划一个计时器, timeout()
回调存储在Web API中:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SLk0AUa5-1611275604642)(/img/bVcMQdg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zr7usYTK-1611275604643)(/img/bVcMQc9)]
B)调用堆栈执行 Promise.resolve(true).then(resolve)
并安排一个 promise
解决方案。 resolved()
回调存储在Web API中:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JTwSnLYS-1611275604646)(/img/bVcMQdh)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k5cRhqzN-1611275604648)(/img/bVcMQdi)]
C)promise 立即被解析,同时计时器也立即执行。这样,定时器回调timeout()
进入任务队列,promise
回调resolve()
进入作业队列
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iMfLB2YJ-1611275604649)(/img/bVcMQdS)]
D)现在是有趣的部分:作业队列(微任务)优先级高于任务队列(宏任务)。 事件循环从作业队列中取出promise回调resolve()
并将其放入调用堆栈中。 然后,调用堆栈执行promise回调resolve()
:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nnqfgoo1-1611275604650)(/img/bVcMQey)]
E)最后,事件循环将计时器回调timeout()
从任务队列中出队到调用堆栈中。 然后,调用堆栈执行计时器回调timeout()
:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fj54WaI0-1611275604650)(/img/bVcMQeB)]
调用堆栈为空,已完成脚本的执行。
以上是“Promise比setTimeout()快的原因有哪些”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。