javascript - 关于事件循环代码片段的随机结果
问题描述
我正在研究 javascript 事件循环,我尝试了一些复杂的嵌套异步代码,其中一个让我非常复杂。代码片段如下:</p>
console.log(1);
new Promise((resolve, reject) => {
console.log(2);
resolve();
}).then(() => {
setTimeout(() => { console.log(3) }, 0);
});
setTimeout(() => {
new Promise((resolve, reject) => {
console.log(4);
resolve();
}).then(() => { console.log(5) });
});
结果有时是 1 - 2 - 4 - 5 - 3,有时是 1 - 2 - 4 - 3- 5。
它在浏览器环境和节点环境中执行相同的操作。
也许我的代码写错了,或者 V8 解决事件循环存在一些问题?
解决方案
您正在结合两件事:Promise.resolve
和window.setTimeout
. 前者同步运行并立即将已解决的项目放入队列中。然而window.setTimeout
,有一个不同的方法。一旦计时器到期,它就会开始处理提供的函数。当使用你在第一个承诺中使用0
的延迟时:window.setTimeout
setTimeout(() => { console.log(3) }, 0);
那么它并不意味着“立即运行”。更多的是“尽快运行此功能”。这可以更改,因为计时器正在被浏览器限制。如果您在阅读某些规范时没有问题,您可以阅读timer-initialisation-steps
以了解它是如何被详细初始化的。
在 MDN 上有一个更容易阅读的信息:延迟时间超过指定的原因
依赖于浏览器/引擎,引擎可能正忙于(后台)任务,因此计时器会受到限制。正如您亲身经历的那样,在某些情况下您会得到不同的结果。最小限制时间是(根据规范,但浏览器可以使用不同的值)4 毫秒。最终结果是节流计时器中的函数在另一个没有被节流的计时器之后执行。
推荐阅读
- django - 为什么即使数据保存在数据库中,django 中的 obj.save() 也会返回“none”
- javascript - 正则表达式解析 odata 查询
- php - Postgres - 是否可以将 search_path 设置为多个模式?
- vue.js - Vue好表添加类到活动行
- json - 将 Next.js 应用程序部署到 Vercel 时出现无效的 json 响应正文错误
- sql - 如何从另一个表中查找包含多个值的行
- c - rd_kafka_consumer_poll() 大多数时候返回 null
- java - 如何在firebase数据库android java中使用where查询
- swift - RealityKit – 哪个实体与其他实体相交
- javascript - 如何使用Jquery动态查找两个输入的百分比