温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

web中Promise.resolve().then(callback)比setTimeout(callback,0)更快的原因是什么

发布时间:2022-03-05 11:27:23 来源:亿速云 阅读:202 作者:小新 栏目:web开发

这篇文章给大家分享的是有关web中Promise.resolve().then(callback)比setTimeout(callback,0)更快的原因是什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

一、实验

让我们尝试一个实验。什么执行得更快:立即解决的承诺或立即超时(也就是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)更快的原因是什么”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

web
AI