JavaScript Learning Notes [setTimeout]
Let’s look at two examples
console.log(1);
setTimeout(function () {
console.log(2);
}, 0);
console.log(3);
Copy the code
The code above outputs 1, 3, 2
Regardless of the execution time of setTimeout is 0 or 1000, the result is 3 followed by 2
for (var i = 0; i < 4; i++) {
setTimeout(function () {
console.log(i);
}, 1000);
}
Copy the code
The output is 4, 4, 4, 4
Single threaded JavaScript
The first thing we need to know is that JavaScript is single-threaded. JS can only do one thing at a time, which is often referred to as “blocking execution.”
Asynchrony can be used for non-blocking execution.
Task queue: A first-in, first-out queue that holds events and tasks.
All tasks can be categorized into two types, synchronous and asynchronous.
Synchronization task: a task that is queued to be executed on the main thread can be executed only after the previous task is completed.
- The output
- Declaration of variables
- Synchronization function
Asynchronous tasks:
- SetTimeout and setInterval
- DOM events
- Promise
- process.nextTick
- fs.readFile
- http.get
- An asynchronous function
In addition, task queues are divided into macro-tasks and micro-tasks. In ES5 standard, they are called tasks and jobs respectively.
Second, setTimeout operation mechanism
SetTimeout is asynchronous, and the running mechanism is the specified code. It will not be executed until all synchronous code has been executed.
Priority relationship: Asynchronous tasks are suspended and executed first. Asynchronous tasks respond to asynchronous tasks only after they are completed.
Here is an example of asynchronous execution:
The browser has a timer module, and the timer will not put the asynchronous task into the asynchronous queue until the execution time. During the execution of the for loop, setTimeout is not put into the asynchronous queue, but given to the timer module.
The four loop bodies execute very fast (less than 1 millisecond). The timer (4 ms by default even if 0 is set) does not place the setTimeout statement on the asynchronous queue until the set time.
The source calls me Townsson
Third, solutions
For the second example above to get 0, 1, 2, 3, you can use the following method.
Method 1: Use let
Use let, not var, because let is scoped, so the value of setTimeout points to the value in each loop body
for (let i = 0; i < 4; i++) {
setTimeout(function () {
console.log(i);
}, 1000);
}
Copy the code
Method two: Use closures
for (var i = 0; i < 4; i++) {
(function (i) {
setTimeout(function () {
console.log(i);
}, 1000 * i)
})(i);
}
Copy the code
Because the value of each I is passed into function, the scope of I in setTimeout is in this closure
Promise based solution
const tasks = [];
const output = (i) = > new Promise((resolve) = > {
setTimeout(() = > {
console.log(i);
resolve();
}, 1000 * i);
});
// Generate all asynchronous operations
for (var i = 0; i < 5; i++) {
tasks.push(output(i));
}
// When the synchronization operation is complete, print the last I
Promise.all(tasks).then(() = > {
setTimeout(() = > {
console.log(i);
}, 1000)})Copy the code
A solution using the async await feature in ES7
const sleep = (timeountMS) = > new Promise((resolve) = > {
setTimeout(resolve, timeountMS);
});
(async() = > {// Declare async to be executed
for (var i = 0; i < 5; i++) {
await sleep(1000);
console.log(i);
}
await sleep(1000);
console.log(i); }) ();Copy the code
References:
www.cnblogs.com/tangjianqia… www.jianshu.com/p/3facc9bd8…