关于html5:面试官为什么-Promise-比setTimeout-快

36次阅读

共计 2212 个字符,预计需要花费 6 分钟才能阅读完成。

作者:Milos Protic
译者:前端小智
起源:devinduct

点赞再看 ,微信搜寻【大迁世界】,B 站关注【前端小智】 这个没有大厂背景,但有着一股向上踊跃心态人。本文 GitHub https://github.com/qq44924588… 上曾经收录,文章的已分类,也整顿了很多我的文档,和教程材料。

最近开源了一个 Vue 组件,还不够欠缺,欢送大家来一起欠缺它,也心愿大家能给个 star 反对一下,谢谢各位了。

github 地址:https://github.com/qq44924588…

1. 试验

咱们来做个试验。哪个执行得更快: 立刻解决的 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)是一个动态函数,它返回一个立刻解析的 promisesetTimeout(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!'

这是为啥呢?

2. 事件循环

与异步 JS 相干的问题能够通过钻研事件循环来答复。咱们回顾一下异步 JS 工作形式的次要组成部分。

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

Web api 是异步操作 (fetch 申请、promise、计时器) 及其回调期待实现的中央。

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

job queue(作业队列)是一个 FIFO(先入先出)构造,它保留筹备执行的 promise 的回调。例如,已实现的承诺的resolvereject回调被排在作业队列中。

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

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 回调)的优先级更高。

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


代码部署后可能存在的 BUG 没法实时晓得,预先为了解决这些 BUG,花了大量的工夫进行 log 调试,这边顺便给大家举荐一个好用的 BUG 监控工具 Fundebug。

原文:https://dmitripavlutin.com/ja…

交换

文章每周继续更新,能够微信搜寻「大迁世界」第一工夫浏览和催更(比博客早一到两篇哟),本文 GitHub https://github.com/qq449245884/xiaozhi 曾经收录,整顿了很多我的文档,欢送 Star 和欠缺,大家面试能够参照考点温习,另外关注公众号,后盾回复 福利,即可看到福利,你懂的。

正文完
 0