十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
这篇文章给大家分享的是有关web中Promise.resolve().then(callback)比setTimeout(callback,0)更快的原因是什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
如皋网站建设公司创新互联公司,如皋网站设计制作,有大型网站制作公司丰富经验。已为如皋上1000家提供企业网站建设服务。企业网站搭建\成都外贸网站建设公司要多少钱,请找那个售后服务好的如皋做网站的公司定做!
一、实验
让我们尝试一个实验。什么执行得更快:立即解决的承诺或立即超时(也就是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)是一个静态函数,它返回一个立即解决的承诺。setTimeout(callback, 0)以0毫秒的延迟执行回调。
打开演示并检查控制台。您会注意到'Resolved!'首先记录的是 ,然后是'Timeout completed!'。立即解决的承诺比立即超时处理得更快。
承诺过程可能会更快,因为Promise.resolve(true).then(...)在setTimeout(..., 0)? 够公平的问题。
我们稍微改变一下实验的条件,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!'.
实验表明,在立即超时之前处理立即解决的承诺。最大的问题是……为什么?
2.事件循环
与异步 JavaScript 相关的问题可以通过调查事件循环来回答。让我们回顾一下异步 JavaScript 工作原理的主要组成部分。
注意:如果您不熟悉事件循环,我建议您在进一步阅读之前先观看此视频。
调用堆栈是一个 LIFO(后进先出)结构,用于存储代码执行期间创建的执行上下文。简单来说,调用堆栈执行函数。
Web API是异步操作(获取请求、承诺、计时器)及其回调等待完成的地方。
任务队列(也称为宏任务)是一个 FIFO(先进先出)结构,它保存准备执行的异步操作的回调。例如,超时的回调setTimeout()——准备执行——被排入任务队列。
作业队列(也称为微任务)是一个 FIFO(先进先出)结构,用于保存准备执行的承诺回调。例如,已履行的承诺的解决或拒绝回调在作业队列中排队。
最后,事件循环会永久监控调用堆栈是否为空。如果调用堆栈为空,则事件循环会查看作业队列或任务队列,并将任何准备执行的回调出列到调用堆栈中。
3. 作业队列 vs 任务队列
我们再从事件循环的角度来看这个实验。我会一步一步分析代码执行。
A) 调用栈执行setTimeout(..., 0)并调度一个定时器。timeout()回调存储在Web API 中:
setTimeout(function timeout() {
console.log('Timed out!');
}, 0);
Promise.resolve(1).then(function resolve() {
console.log('Resolved!');
});
B) 调用堆栈执行Promise.resolve(true).then(resolve)并安排承诺解决方案。resolved()回调存储在Web API 中:
setTimeout(function timeout() {
console.log('Timed out!');
}, 0);
Promise.resolve(1).then(function resolve() {
console.log('Resolved!');
});
C)承诺立即解决,计时器立即超时。因此,定时器回调timeout()被排入任务队列,promise 回调resolve()被排入作业队列:
D)现在是有趣的部分:事件循环优先于任务出列作业。事件循环resolve()从作业队列中取出承诺回调并将其放入调用堆栈中。然后调用堆栈执行承诺回调resolve():
setTimeout(function timeout() {
console.log('Timed out!');
}, 0);
Promise.resolve(1).then(function resolve() {
console.log('Resolved!');
});
'Resolved!' 记录到控制台。
E) 最后,事件循环将计时器回调timeout()从任务队列中出列到调用堆栈中。然后调用堆栈执行定时器回调timeout():
setTimeout(function timeout() {
console.log('Timed out!');
}, 0);
Promise.resolve(1).then(function resolve() {
console.log('Resolved!');
});
'Timed out!' 记录到控制台。
调用堆栈为空。脚本执行已完成。
4. 总结
为什么立即解决的承诺比立即计时器处理得更快?
由于事件循环优先级使作业队列(存储已履行的承诺的回调)中的作业优先于任务队列(存储超时setTimeout()回调)中的任务。
感谢各位的阅读!关于“web中Promise.resolve().then(callback)比setTimeout(callback,0)更快的原因是什么”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!