setTimeout(fn,0)
https://javascript.plainenglish.io/what-is-the-javascript-event-loop-84d21ef276ee
The first two arguments to the function setTimeout are a message to add to the queue and a time value (optional; defaults to 0). The time value represents the (minimum) delay after which the message will be pushed into the queue. If there is no other message in the queue, and the stack is empty, the message is processed right after the delay. However, if there are messages, the setTimeout message will have to wait for other messages to be processed. For this reason, the second argument indicates a minimum time — not a guaranteed time.
Asynchronous Web API Examples
Let’s look at the setTimeout Web API first. As you may know, setTimeout takes two arguments, a callback function, and a time (in milliseconds) until the execution of the callback. Let’s see what happens when we pass our sayHi function in as the callback of setTimeout:
Our setTimeout function is sent to the Web APIs container after it is processed in the Call Stack. After 3000 ms (3 seconds), the callback sayHi() is sent to the Callback Queue where it waits for the end of the synchronous code to finish running and is then dequeued and run in the Call Stack. Something to note: the 3000 ms time that we set is the minimum amount of time it will be before the callback is run. If our synchronous code is still being executed in the Call Stack when the 3000 ms is over, the callback will still have to wait until all of the code has been completed before it will be sent to the Call Stack. Let’s set the setTimeout time to 0 and see this in action:
This clearly demonstrates how the Callback Queue isn’t run until our Call Stack is empty, even if the time has passed on our setTimeout function.
Here is an example that demonstrates this concept (setTimeout does not run immediately after its timer expires):
const seconds = new Date().getTime() / 1000;
setTimeout(() => {
// prints out "2", meaning that the callback is not called immediately after 500 milliseconds.
console.log(`Ran after ${new Date().getTime() / 1000 - seconds} seconds`);
}, 500);
while (true) {
if (new Date().getTime() / 1000 - seconds >= 2) {
console.log("Good, looped for 2 seconds");
break;
}
}
Zero delay doesn't mean the call back will fire-off after zero milliseconds. Calling setTimeout with a delay of 0 (zero) milliseconds doesn't execute the callback function after the given interval.
The execution depends on the number of waiting tasks in the queue. In the example below, the message "this is just a message" will be written to the console before the message in the callback gets processed, because the delay is the minimum time required for the runtime to process the request (not a guaranteed time).
The setTimeout needs to wait for all the code for queued messages to complete even though you specified a particular time limit for your setTimeout.
(() => {
console.log("this is the start");
setTimeout(() => {
console.log("Callback 1: this is a msg from call back");
}); // has a default time value of 0
console.log("this is just a message");
setTimeout(() => {
console.log("Callback 2: this is a msg from call back");
}, 0);
console.log("this is the end");
})();
// "this is the start"
// "this is just a message"
// "this is the end"
// "Callback 1: this is a msg from call back"
// "Callback 2: this is a msg from call back"
setTimeout一定会定时执行吗?不一定(expamle:在加载页面时推迟超时)
如果浏览器主线程一直被占据,那么setTimeout会什么时候执行?
console.log(2)
setTimeout(()=>{console.log(1000)},1000)
console.log(1)
setTimeout(()=>{console.log(2000)},1000)
setTimeout(()=>{console.log(3000)},1000)
setTimeout(()=>{console.log(0)},0)
setTimeout(()=>{console.log(5000)},1000)
console.log(4)
setTimeout(()=>{console.log(4000)},1000)
console.log(5)
2
1
4
5
0
同时输出 1000 2000 3000 5000 4000
console.log(2)
setTimeout(()=>{console.log(1000)},1000)
console.log(1)
setTimeout(()=>{console.log(2000)},2000)
setTimeout(()=>{console.log(3000)},3000)
setTimeout(()=>{console.log(0)},0)
setTimeout(()=>{console.log(5000)},4000)
console.log(4)
setTimeout(()=>{console.log(4000)},5000)
console.log(5)
2
1
4
5
0
1000 //1m后
2000//2m后
3000//3m后
5000//4m后
4000//5m后