文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

面试官:为什么 Promise 比setTimeout() 快?

2024-12-03 13:12

关注

本文已经过原作者 devinduct 授权翻译。

1.实验

我们来做个实验。哪个执行得更快:立即解决的 Promise 还是立即setTimeout(也就是0毫秒的setTimeout)?

  1. Promise.resolve(1).then(function resolve() { 
  2.   console.log('Resolved!'); 
  3. }); 
  4.  
  5. setTimeout(function timeout() { 
  6.   console.log('Timed out!'); 
  7. }, 0); 
  8.  
  9. // 'Resolved!' 
  10. // 'Timed out!' 

promise.resolve(1)是一个静态函数,它返回一个立即解析的promise。setTimeout(callback, 0)以0毫秒的延迟执行回调函数。

我们可以看到先打印'Resolved!',再打印Timeout completed!,立即解决的 promise 比立即setTimeout更快。

是因为Promise.resolve(true).then(...)在setTimeout(..., 0)之前被调用了,所以 Promise 过程会更快吗?公平的问题。

所以,我们稍微更改一下实验条件,然后先调用setTimeout(..., 0):

  1. setTimeout(function timeout() { 
  2.   console.log('Timed out!'); 
  3. }, 0); 
  4.  
  5. Promise.resolve(1).then(function resolve() { 
  6.   console.log('Resolved!'); 
  7. }); 
  8.  
  9. // 'Resolved!' 
  10. // 'Timed out!' 

setTimeout(..., 0)在Promise.resolve(true).then(...)之前被调用。但,还是先打印Resolved!在打印'Timed out!'。

这是为啥呢?

2.事件循环

与异步 JS 相关的问题可以通过研究事件循环来回答。我们回顾一下异步 JS 工作方式的主要组成部分。

 

调用堆栈是一个LIFO(后进先出)结构,它存储在代码执行期间创建的执行上下文。简单地说,调用堆栈执行这些函数。

Web api是异步操作(fetch 请求、promise、计时器)及其回调等待完成的地方。

**task queue (任务队列)是一个FIFO(先进先出)**结构,它保存准备执行的异步操作的回调。例如,超时的setTimeout()的回调函数或准备执行的单击按钮事件处理程序都在任务队列中排队。

**job queue (作业队列)**是一个FIFO(先入先出)结构,它保存准备执行的promise 的回调。例如,已完成的承诺的resolve或reject回调被排在作业队列中。

最后,事件循环永久监听调用堆栈是否为空。如果调用堆栈为空,则事件循环查看作业队列或任务队列,并将准备执行的任何回调分派到调用堆栈中。

3.作业队列与任务队列

我们从事件循环的角度来看这个实验,我将对代码执行进行一步一步的分析。

A)调用堆栈执行setTimeout(..., 0)并计划一个计时器, timeout()回调存储在Web API中:

 

B)调用堆栈执行 Promise.resolve(true).then(resolve)并安排一个 promise 解决方案。resolved()回调存储在Web API中:

 

C)promise 立即被解析,同时计时器也立即执行。这样,定时器回调timeout()进入任务队列,promise回调resolve()进入作业队列

 

D)现在是有趣的部分:作业队列(微任务)优先级高于任务队列(宏任务)。事件循环从作业队列中取出promise回调resolve()并将其放入调用堆栈中。然后,调用堆栈执行promise回调resolve():

 

E)最后,事件循环将计时器回调timeout()从任务队列中出队到调用堆栈中。然后,调用堆栈执行计时器回调timeout():

 

调用堆栈为空,已完成脚本的执行。

总结

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

由于事件循环优先级的存在,因此与任务队列(存储超时的setTimeout()回调)相比,作业队列(用于存储已实现的Promise回调)的优先级更高。

完~ 我是小智,我要去刷碗了,我们下期见!

 

作者:Milos Protic 译者:前端小智 来源:devinduct原文:https://dmitripavlutin.com/javascript-promises-settimeout/

本文转载自微信公众号「 大迁世界」,可以通过以下二维码关注。转载本文请联系 大迁世界公众号。

 

来源:大迁世界内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯