您现在的位置是:亿华云 > 应用开发
为什么 Promis 比setTimeout()更快?
亿华云2025-10-04 00:20:02【应用开发】9人已围观
简介实验先做一个实验:来看看立即解决的 Promis 和立即超时( 0 毫秒的超时)哪个执行的更快?Promise.resolve(1).then(functionresolve(){console.lo
实验
先做一个实验:来看看立即解决的 Promis 和立即超时( 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) 是一个静态函数,可返回立即解决的 promise。setTimeout(callback, 0) 执行延迟为 0 毫秒的回调。
打开执行并检查控制台。您会看到日志先打印了 Resolved! ,然后打印了 Timeout completed!。立即解决的承诺比立即超时处理得更快。
是因为 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!); }); // logs Resolved! // logs Timed out!执行并查看控制台,结果是一样的!
尽管 setTimeout(..., 0) 在 Promise.resolve(true).then(...) 之前被调用了,但是 Resolved! 仍然在 Timed out! 之前被输出。
实验表明,立即解决的 promise 在立即超时之前已得到处理。所以。。。这是为什么?
事件循环
与异步 JavaScript 有关的问题可以通过探索事件循环解答答。站群服务器先回顾一下异步 JavaScript 的工作原理。
空的事件循环
调用栈(call stack) 是 LIFO(后进先出)的结构,用于存储在代码执行期间创建的执行上下文。简而言之,调用栈执行用来函数。
Web API 是异步操作(fetch 请求、promises、计时器),回调等待这里的工作完成。
**任务队列(task queue)**是一个 FIFO(先进先出)的结构,其中包含准备好执行的异步操作的回调。例如,超时的 setTimeout() 的回调(准备执行)进入任务队列中。
工作队列(job queue) 是一个 FIFO(先进先出)的结构,其中包含准备执行的 promise 的回调。例如,香港云服务器已解决的 resolve 或拒绝回调进入工作队列中。
最后,事件循环(event loop) 会一直监视调用栈是否为空。如果调用栈为空,则事件循环会查找工作队列或任务队列,并使准备好执行的回调出队到调用栈中。
工作队列与任务队列
下面从事件循环的角度来看一下前面的实验。我会逐步分析代码的执行情况。
(1) 调用堆栈执行 setTimeout(..., 0) 并“安排”一个计时器。timeout() 回调存储在 Web API 中:
setTimeout(function timeout() { console.log(Timed out!);}, 0); Promise.resolve(1).then(function resolve() { console.log(Resolved!); });事件循环
(2) 调用栈执行 Promise.resolve(true).then(resolve) 并“安排”一个 promise 解析。resolved() 回调存储在 Web API 中:
setTimeout(function timeout() { console.log(Timed out!); }, 0); Promise.resolve(1).then(function resolve() { console.log(Resolved!);});事件循环
(3) promise 立即解决,计时器立即超时。这时计时器回调 timeout() 被“排队”到任务队列,promise 回调 resolve() 被“排队”到工作队列:
事件循环
(4) 这里是最有意思部分:事件循环优先级使工作排在任务之上。事件循环使 promise 回调 resolve() 从工作队列中出队,并将其放入调用栈中,然后调用栈执行 promise 回调 resolve():
setTimeout(function timeout() { console.log(Timed out!); }, 0); Promise.resolve(1).then(function resolve() { console.log(Resolved!);});Resolved! 被输出到控制台。
Event Loop
(5) 最后,事件循环把计时器回调 timeout() 从任务队列中移出到调用栈中。然后调用栈执行计时器回调timeout():
setTimeout(function timeout() { console.log(Timed out!);}, 0); Promise.resolve(1).then(function resolve() { console.log(Resolved!); });Timed out! 已输出到控制台。
Event Loop
此时调用栈为空。脚本执行已完成。
总结
为什么立即解决的 promise 比立即计时器处理得更快?
是由于事件循环的“优先级”使任务队列(存储已实现的高防服务器 promise 的回调)中的任务从任务队列(存储超时的setTimeout() 回调)中的任务中出队。
很赞哦!(34)
相关文章
- 域名资源有限,好域名更是有限,但机会随时都有,这取决于我们能否抓住机会。一般观点认为,国内域名注册太深,建议优先考虑外国注册人。外国注册人相对诚实,但价格差别很大,从几美元到几十美元不等。域名投资者应抓住机遇,尽早注册国外域名。
- 网站目录和二级域名的区别是什么?做站有何不同?
- 新顶级域名怎么与COM争天下?com域名将如何展开攻势?
- 那些被关停的平台域名如何了?有什么好的前景?
- 4、待所有域名查询结束后可在右侧点击导出结果,即可以excel的文件方式将查询到的结果导出。
- 新手对不同级数域名怎么看?有什么好的优化方法?
- 二级域名怎么优化关键字?二级域名有什么好处?
- 二级域名有限制吗?二级域名是独立的网站吗?
- 4、参加域名拍卖会
- 新手一般是怎么挑选企业域名名称?有什么诀窍?