为什么即使延迟为 0 毫秒,函数执行后仍会调用 setTimeout 回调?
Why is the `setTimeout` callback called after function execution, even if the delay is 0 ms?
setTimeout(function(){
console.log("m");
}, 0);
console.log("s");
为什么此代码在 "m"
之前打印 "s"
,即使 setTimeout
回调应该等待 0 毫秒?
浏览器或node.js总是运行单线程事件循环到运行你的代码。在第一个 运行 上,它总是 运行 您的同步代码,但也可能会查询稍后回调的异步事件。这就是我们在这里调用该函数的原因 callback function
稍后将调用它。
setTimeout
是一个微任务。
这意味着你看到的 function
不是立即执行的,它会首先排队并在下一个事件循环中执行。
还有一个副作用:0 ms
只是意味着它将最少等待 0 ms
不准确 0
当您创建承诺、调用异步函数或将超时设置为 0 毫秒时,该函数会立即排队进入 Javascript event loop。本质上,该函数被添加到要调用的函数队列中,一旦 javascript 解释器无事可做,它就会开始调用这些函数。因此,当您将超时设置为 0 毫秒时,它会将 console.log("m")
排队,然后调用 console.log("s")
,然后它无事可做,因此它会完成排队的 console.log("m")
,这就是它的原因乱序。
这只是因为 JS 是单线程的,事件循环就是这样工作的。
setTimeout 以一种方式编写,它将向您发送函数或您想要在回调队列中执行的任何操作。
然后前进到下一行,一旦下一行执行它不会运行你的setTimeout部分,或者换句话说,它不会处理setTimeout部分直到堆栈不为空。
所以这是你的代码,它将像这样执行。
setTimeout(function () {
console.log("m");
} , 0)
console.log('s');
- 第一行将执行并将setTimeout的内部发送到回调队列并移动到第二行。
- 当第 2 行正在执行 setTimeout 部分时,将等待直到堆栈不为空,一旦第 2 行执行完毕,
- setTimeout 部分将执行,
可能说的比较糊涂,我们看实际操作吧。我打赌你找不到比这更好的例子来理解它,它在 the best way by Philip robert.
中有解释
因为JS代码是一条一条的。当您将 setTimeout 指定为 0 时仍在等待,在 C++ lang 中,这将是这样的 0.000000245ms,而 JS 经常在 C++/C 浏览器上运行。
试试这个简单的例子
for (let x = 0; x < 500; x++) {
setTimeout(() => console.log(x), 0);
}
console.log('hello');
setTimeout(function(){
console.log("m");
}, 0);
console.log("s");
为什么此代码在 "m"
之前打印 "s"
,即使 setTimeout
回调应该等待 0 毫秒?
浏览器或node.js总是运行单线程事件循环到运行你的代码。在第一个 运行 上,它总是 运行 您的同步代码,但也可能会查询稍后回调的异步事件。这就是我们在这里调用该函数的原因 callback function
稍后将调用它。
setTimeout
是一个微任务。
这意味着你看到的 function
不是立即执行的,它会首先排队并在下一个事件循环中执行。
还有一个副作用:0 ms
只是意味着它将最少等待 0 ms
不准确 0
当您创建承诺、调用异步函数或将超时设置为 0 毫秒时,该函数会立即排队进入 Javascript event loop。本质上,该函数被添加到要调用的函数队列中,一旦 javascript 解释器无事可做,它就会开始调用这些函数。因此,当您将超时设置为 0 毫秒时,它会将 console.log("m")
排队,然后调用 console.log("s")
,然后它无事可做,因此它会完成排队的 console.log("m")
,这就是它的原因乱序。
这只是因为 JS 是单线程的,事件循环就是这样工作的。 setTimeout 以一种方式编写,它将向您发送函数或您想要在回调队列中执行的任何操作。 然后前进到下一行,一旦下一行执行它不会运行你的setTimeout部分,或者换句话说,它不会处理setTimeout部分直到堆栈不为空。
所以这是你的代码,它将像这样执行。
setTimeout(function () {
console.log("m");
} , 0)
console.log('s');
- 第一行将执行并将setTimeout的内部发送到回调队列并移动到第二行。
- 当第 2 行正在执行 setTimeout 部分时,将等待直到堆栈不为空,一旦第 2 行执行完毕,
- setTimeout 部分将执行,
可能说的比较糊涂,我们看实际操作吧。我打赌你找不到比这更好的例子来理解它,它在 the best way by Philip robert.
中有解释因为JS代码是一条一条的。当您将 setTimeout 指定为 0 时仍在等待,在 C++ lang 中,这将是这样的 0.000000245ms,而 JS 经常在 C++/C 浏览器上运行。
试试这个简单的例子
for (let x = 0; x < 500; x++) {
setTimeout(() => console.log(x), 0);
}
console.log('hello');