当前位置: 首页 > 知识库问答 >
问题:

javascript - chrome中测试setTimeout设置为0,为什么会出现不符合预期规范的情况?

督飞鸣
2023-08-24

问题描述

在测试下列代码:

setTimeout(() => {    console.log(1)}, 20)for (let i = 0; i < 999999999; i++) {    // do something 40ms}setTimeout(() => {    console.log(2)}, 0)

根据定时器的相关规范,预测结果应该是:
1,2
因为第一个定时器先注册,在浏览器API或Node中完成计时后,进入宏任务队列,那么栈顶肯定是他;等for循环结束后,第二个定时器注册,并同样在完成计时后,进入宏任务队列;最后,执行宏任务队列,输出就应该是1,2。

实际测试结果:
chrome:2,1
edge:2,1
firefox:1,2
node:1,2

测试环境

chrome:115.0.5790.172(正式版本) (64 位)
edge:115.0.1901.203 (正式版本) (64 位)
firefox(developer):117.0b6 (64 位)
node:v18.16.1

(笔记本性能:32gb内存,AMD Ryzen 7 5800H,应该可以排除硬件问题)

尝试理解其原因

  1. 基于chromium内核的浏览器,定时器实现存在差异。
  2. 可能是for循环导致的,我换成另一种方式阻塞,输出的结果就符合预期。
setTimeout(() => {    console.log(1)}, 20)await new Promise((resolve, reject) => setTimeout(resolve, 3000));setTimeout(() => {    console.log(2)}, 0)

这段代码,在chrome和edge中测试都是输出为1,2。

请教问题

出现这种情况是到底是什么原因导致的呢?chrome浏览器和设置定时器为0都是挺常用的,还望大佬不吝赐教。

共有1个答案

艾飞宇
2023-08-24

setTimeout 0应该是被优化直接放到宏队列头了,虽然时间到了,但是当前执行并没有完成,所以第一个20毫秒的定时器超时任务还不会被调度如何会出现在宏队列头,所以在宏队列并不会出现在0毫秒之前,这才是正确的

输出1 2才是有问题的,firefox和node输出这个,应该是setTimeout虽然被设置为0毫秒超时,但实际内部有最小超时时间,并不是0毫秒超时的,所以自然会在第一个20毫秒后面执行了

使用await会输出1 2是应该await里边的setTimeout时间较长,当前执行已经切换出去,第一个setTimeout就可以被调度到了,自然先执行,也是正确的

 类似资料:
  • 问题内容: 我最近遇到了一个令人讨厌的错误,该错误中的代码是通过JavaScript动态加载的。动态加载的具有预先选择的值。在IE6中,我们已经有代码来修复selected ,因为有时的值可能与selected 的属性不同步,如下所示: 但是,此代码无法正常工作。即使正确设置了字段,最终也会选择错误的索引。但是,如果我在正确的时间插入一条语句,则会选择正确的选项。考虑到这可能是某种时序问题,我尝试

  • 原关闭原因未解决 这是我的测试类,它的方法使用NullPointer失败。 正如您所看到的,我甚至尝试在方法中正确初始化时钟,但仍然失败。当我启动应用程序时,它按预期工作。 这是时钟豆 这是个例外 java.lang.NullPointerException:时钟

  • 问题内容: 注意:这不是有关settimeout的复制文章,此处的关键答案是浏览器设计选项。 我开始研究node.js:一个测试异步的简单示例: 一件有趣的事情是,在带有curl的lind命令和浏览器中,它的行为是不同的:在Ubuntu 12.10中,我在两个控制台中使用curl localhost:8080,它们在几乎相同的10个发送中进行响应。 但是,我打开了两个浏览器,几乎同时发出了请求,但

  • 在实用服务中,我有两个功能foo和bar。js 在我的测试文件中,我导入了实用ervice.js并窥探了条形图函数。我期望调用间谍计数为1,因为foo被称为,但它是0。如果我错过了什么,请建议。

  • 我使用JavaScript有这个条件,我有两个文本框,我将在其中比较输入(输入是数字)。条件是当textbox 2小于textbox 1时,它将显示一条警告消息,说明textbox 2必须大于textbox 2。所以当输入是这样的时候 为什么当它将2与9进行比较时,它不会发出任何警报? 以下是我的情况:

  • 我正在编写一个简单的应用程序来保存和查找位置。我用的是猫鼬和茉莉节点。 用户CRUD测试工作符合预期。但是,我单独创建了用户来测试不同的自定义验证。我还通过清除集合并重新加载所有用户来启动测试,以确保在启动save/update/etc测试之前所有测试数据都是良好的。 对于位置,我也在做同样的事情,但我有几十个位置,我想使用数组加载它们。。。并在整个过程中测试负载,确保其正常工作。 如果我只做一个