setTimeout
First appearance of setTimeout
Definition: The setTimeout() method is used to call a function or evaluate an expression after a specified number of milliseconds.Copy the code
Grammar:
setTimeout(code, milliseconds, param1, param2, ...)
setTimeout(function.milliseconds.param1.param2,...).Copy the code
parameter | describe |
---|---|
code/function | A necessity. To call a code string, it can also be a function |
milliseconds | Optional. The amount of time to wait, in milliseconds, to execute or call code/function. The default is 0. |
param1, param2, … | Optional. Additional arguments passed to the executing function (not supported by IE9 and earlier versions). |
SetTimeout first acquaintance
The first kind of
setTimeout(fn1, 1000);
setTimeout(fn2, 2000);
setTimeout(function fn3(){console.log(3); },3000);
setTimeout(function (){console.log(4); },4000);
function fn1(){
console.log(1);
}
var fn2 = function(){
console.log(2);
}
// The output is as follows:
Output 1,2,3,4 after a delay of 1,2,3,4 seconds respectively
Copy the code
The second,
setTimeout(fn1(), 1000);
setTimeout(fn2(), 2000);
setTimeout(function fn3(){console.log(3); } (),3000);
setTimeout(function (){console.log(4); } (),4000);
function fn1(){
console.log(1);
}
var fn2 = function(){
console.log(2);
}
// The output is as follows:
// Direct output 1, 2, 3, 4, no delay
Copy the code
As defined: the setTimeout() method is used to call a function or evaluate an expression after a specified number of milliseconds. The first method executes after the specified number of milliseconds, and the second method executes not after the specified number of milliseconds, but immediately. Therefore, I personally divide it into regular army setTimeout and miscellaneous army setTimeout for the convenience of later memory.
Since the first argument to setTimeout() is directly executable code, it has no delay effect, as follows:
setTimeout(console.log(1), 1000);
// The output is as follows:
// Output 1 directly, no delay
Copy the code
3, setTimeout again
setTimeout(function(a,b){
console.log(a+b);
},1000.4.5);
// The output is as follows:
/ / 9
Copy the code
Bind () : bind (); / / bind (); / / bind (); / / bind (); / / bind (); / / bind (); / / bind ();
setTimeout(function(a,b){
console.log(a+b);
}.bind(this.4.5),1000);
// The output is as follows:
/ / 9
Copy the code
The first argument binds the function’s this to the global scope. The second argument starts with the argument to be passed to the function. When the binding function is called, the binding function takes as this the first argument passed to the bind() method when it was created
Four, setTimeout
For this problem of setTimeout(), there are many articles on the Internet. I will not teach you how to play the game. If the summary is enough in place, I will write an article to introduce it.
console.log(1);
setTimeout(function (){
console.log(2);
},3000);
console.log(3);
// The output is as follows:
/ / 1 2 3
Copy the code
console.log(1);
setTimeout(function (){
console.log(2);
},0);
console.log(3);
// The output is as follows:
/ / 1 2 3
Copy the code
Some of you might be wondering, well, it’s understandable that the first piece of code is delayed by three seconds to print 1,3,2, but why is the second piece of code delayed by zero seconds to print 1,3,2?
This is where the concept of “task queues” comes in, and since JavaScript is a single-threaded language, you can only do one thing at a time. However, HTML5 proposes the Web Worker standard, which allows JavaScript scripts to create multiple threads, but the child threads are completely controlled by the main thread. Single-threaded means that all tasks need to be queued until the previous task finishes before the next task can be executed. If the first task takes a long time, the second task has to wait forever.
So designers divide tasks into two types, one is synchronous and the other is asynchronous. A synchronization task is a task that is queued to be executed on the main thread. A synchronization task can be executed only after the first one is executed. Asynchronous tasks are tasks that do not enter the main thread but enter the “task queue”. Only when the “task queue” notifies the main thread that an asynchronous task is ready for execution, the task will enter the main thread for execution.
Task Queue can place timed events as well as task events. That is, specify how much time after some code is executed. With that in mind, we can basically explain why the above two pieces of code produce the results that they do.
The first piece of code, because setTimeout() delays the callback for 3000 milliseconds. If setTimeout() is set to 0, the specified callback is executed immediately after the current code completes execution (0 milliseconds). So only after printing 1 and 3 does the system execute the callback function in the “task queue”.
In short, setTimeout(fn,0) means to specify that a task should be executed at the earliest available free time on the main thread, that is, as early as possible. It adds an event to the end of the “task queue”, so it does not execute until both the synchronized task and the existing events in the “task queue” are processed. Again, it adds an event to the end of the task queue, remember the tail, to the end of the task queue, so it’s executed last.
The HTML5 standard specifies that the second parameter of setTimeout() must be at least 4 milliseconds, and if it is below this value, it is automatically increased. Previously, older browsers had set the minimum interval to 10 milliseconds.
SetTimeout () simply inserts the event into the “task queue” and must wait until the current code (execution stack) completes before the main thread executes its specified callback function. If the current code takes a long time, it may take a long time, so there is no guarantee that the callback will be executed at setTimeout(). So sometimes they are not always punctual. Good boys are those who are punctual!
Ruan Yifeng has a detailed introduction to the task queue, please click here for details
5. SetTimeout is familiar
With that in mind, we need to pull out the yo-yo and go straight to the quiz:
console.log(1);
setTimeout(fn1, 1000);
setTimeout(function(){
console.log(2);
},0);
setTimeout(console.log(3),2000);
function fn1(){
console.log(4);
}
console.log(5);
// Output result:
//1 3 5 2 4(4 will delay one second)
Copy the code
1. Run the main thread and print 1.
2. When the first setTimeout is encountered, the callback function will be executed after 1 second, so it is added to the task queue;
3. When the second setTimeout is encountered, the callback function will be executed after 0 seconds and the task will be added to the task queue again.
The third setTimeout is encountered. The first parameter is not a callback function, but a directly executable statement. Remember that this is a miscellaneous statement that does not add to the task queue or delay execution, but executes directly, so print 3;
5. Continue to print 5.
6. The second setTimeout, because it is 0 second delay, the main thread task is executed immediately after completion, so print 2;
7. Execute the first setTimeout and print 4 after one second.
After we understand the above questions, we can understand the following code:
var timeoutId = setTimeout(function (){
console("hello World");
},1000);
clearTimeout(timeoutId);
// Output result:
// Will not print Hello World
Copy the code
1. Execute the main thread first, setTimeout is encountered and the first parameter is a callback function, add to the task queue, execute 1 second later;
2. Execute clearTimeout, and the timer is cancelled before the code executes, so nothing is printed.
Let’s look at promises
promise
First, promise
ES6 has written promise into the language standard, unified usage, and provided promise objects natively. Ruan Yifeng teacher gave a detailed explanation;
Here’s a quick rundown of what I’ll be using later: The Promise is created and executed immediately, and the then method takes two callback functions as arguments and won’t execute until all synchronization tasks in the current script have been executed. Remember that callbacks after THEN are executed asynchronously, so they are added to the task queue. The first callback is called when the Promise object’s state changes to Resolved. The second callback is called when the Promise object’s state changes to Rejected. The second function is optional and does not have to be provided.
I made a promise
Below I will look at the various interview questions gradually in the form of code snippets to deepen your understanding
console.log(1);
new Promise((resolve,reject) = >{
console.log(2);
resolve()
}).then( (a)= >{
console.log(3)}, () = > {console.log(4);
});
console.log(5);
// Output result:
/ / 1 2 3 5
Copy the code
1. Run the main thread and print 1.
- Promise is executed immediately after it is created, so print 2 and resolve indicates a successful callback.
- Then is executed asynchronously and is added to the task queue.
- Continue executing the main thread, printing 5;
- Execute the callback function in the task queue after the main thread finishes printing out 3
console.log(1);
new Promise((resolve,reject) = >{
console.log(2);
reject()
}).then( (a)= >{
console.log(3)}, () = > {console.log(4);
});
console.log(5);
// Output result:
/ / 1 2 5 and 4
Copy the code
This example is the same as above, except that it executes an asynchronous failed callback, so the last one prints 4
console.log(1);
new Promise((resolve,reject) = >{
console.log(2);
}).then( (a)= >{
console.log(3)});console.log(4);
// Output result:
4/1/2
Copy the code
In this example, the reason the 3 is not printed after the 4 is because the promise did not specify whether a successful or failed callback should be executed, so the then callback will not be executed
console.log(1);
new Promise((resolve,reject) = >{
console.log(2);
}).then(console.log(3));
console.log(4);
// Output result:
/ / 1 2 3 4
Copy the code
So if you look at this and you’re confused, why is it 1234 instead of 1243, you’re going to have to be careful, but if you look at that then you’re going to have an executable statement instead of a callback, so you’re going to have an asynchronous task that has to be a callback and if it’s not a callback it’s synchronous, right
1. Run the main thread and print 1.
- Promise will be executed as soon as it’s new, so it prints a 2;
- Then is not a callback but a directly executable statement, so it prints 3 directly.
- Continue executing the main thread, printing 4;
Hee hee, after seeing these examples above, I believe that you have understood a lot of promise, so we continue to look at the following example, what is the output result?
console.log(1);
new Promise((resolve,reject) = >{
console.log(2);
resolve();
console.log(3);
}).then( (a)= >{
console.log(4)});console.log(5);
// Output result:
//1 2 3 5 4
Copy the code
Did you get it right? Resolve (), console.log(3); This is because the resolve() call is followed by console.log(3), which is printed first. Because immediate Resolved promises are executed at the end of this cycle, they are always later than the synchronization task in this cycle.
So if you want a Promise to complete after a call to resolve or reject, the subsequent actions should be placed in the then method, not directly after resolve or reject. Therefore, it is best to precede them with a return statement so there are no surprises. As follows:
console.log(1);
new Promise((resolve,reject) = >{
console.log(2);
return resolve();
console.log(3);
}).then( (a)= >{
console.log(4)});console.log(5);
// Output result:
/ / 1 2 5 and 4
Copy the code
So the console. The log (3); It’s not going to happen.
Third, promise&setTimeout
Now let’s look at what happens if a promise&setTimeout occurs at the same time. As follows:
console.log('a');
setTimeout(function() {console.log('b')}, 0);
new Promise((resolve, reject) = > {
for(let i=0; i<10000000; i++) {
if(i==999999) {
console.log('c'); resolve(); }}console.log('d');
}).then((a)= > {
console.log('e');
});
console.log('f');
// Output result:
// a c d f e b
Copy the code
We’re going to have to develop a new concept here to help us understand: event loops, macro tasks and micro tasks
One of the hallmarks of JavaScript is a single thread that has a unique event loop.
Event loops are unique within a thread, but task queues can have multiple.
Task queues are divided into macro-tasks and micro-tasks, which are also known as Tasks and Jobs.
Macro tasks include: Script, setTimeout, setInterval, setImmediate, I/O, UI rendering.
NextTick, Promise, MutationObserver(a new feature of HTML5)
The order of the event loop determines the order in which the JavaScript code is executed.
It starts the first loop with script(the whole code). The global context then enters the function call stack.
Until the call stack is empty (only global), then all micro-tasks are executed.
When all executable micro-tasks have been completed.
The loop starts again with macro-tasks, finds one task queue to complete, and then executes all micro-tasks, and so on.
Note: The macro tasks used in this article are: script(overall code), setTimeout, setInterval; Micro-task: Promise. Other browsers do not use Node.js apis, such as setImmediate, Process.nexttick, etc. See this article for their execution sequence
For example, different types of tasks will enter the task queue of their respective types. For example, all setTimeout() callbacks will enter the setTimeout task queue, i.e. Macro-task. All THEN () callbacks go to the THEN queue, known as micro-tasks.
The current overall code can be thought of as a macro task. Event loop starting from the current overall code first event loop, and then execute all the tasks in the queue, when after the task has been completed, event loop to find one of the macro task queue and perform all the tasks, and then find a micro task queue and perform all the tasks, so had been circulating. This is my understanding of the cycle of events.
Analyze the above example:
1. Execute the whole code first, and print a first
2. When the first setTimeout is executed, it is found to be a macro task. In this case, a new macro task queue of type setTimeout will be created and the callback function of the current setTimeout will be sent to the newly established macro task queue
3. Execute to new Promise. The first argument in the Promise constructor is executed directly on new, so it does not enter any queue, so the third output is c
4. After the resolve() command is executed, proceed to print d
If Promise. Then is a microtask, then a queue of type Promise. Then callbacks will be pushed into this queue
6. Go back and print f
7. The macro task of the first round of the event loop is completed (the whole code is considered as a macro task). There is only one promise. then microtask queue in the microtask queue. There is also only one setTimeout macro task queue in the macro task queue.
8. The first event loop is complete by executing the microtask of the first event loop, which obviously prints e
9. Start the second event loop: Execute all the tasks in the setTimeout type queue (macro task queue), only one task, so print b
10. The macro task for the second round of events ends, and the event loop ends.
Here’s another super example of you in me and you in me, experience the riddled test questions, heh heh; -)
console.log('a');
setTimeout(function () {
console.log('b')
new Promise(resolve= > {
console.log('c')
resolve()
}).then((a)= > {
console.log('d')})},2000);
new Promise((resolve,reject) = >{
console.log('e');
resolve();
console.log('f');
}).then((a)= >{
console.log('g')});console.log('h');
new Promise((resolve,reject) = >{
setTimeout(function () {
console.log('i');
},0);
}).then(console.log('j'));
setTimeout(function () {
console.log('k')
new Promise(resolve= >{
console.log('l')
return resolve()
console.log('m')
}).then((a)= >{
console.log('n')})},1000);
console.log('p');
// Output result:
//a e f h j p g i
// Delay 1s output: k l n
// Delay output for 1s: b c d
Copy the code
1. Execute the whole code first, print “A” first;
2. When the first setTimeout is executed and it is found to be a macro task, a new macro task queue of type setTimeout will be created and the callback function of the current setTimeout will be sent to the newly established macro task queue, and its execution will be delayed for 2 seconds.
3. Execute to the first new Promise. The first argument in the Promise constructor is executed directly on new and therefore does not enter any queue, so the second output is “e”. So the third output is “f”, promise. then is a microtask, so there will be a queue of promise. then, and then callbacks will be pushed into that queue;
4. Execute the whole code again, and print the fourth “H “;
5. Execute to the first new Promise. The first argument in the Promise constructor will be executed when new, but this is a setTimeout. The Promise. Then is an executable code, not a callback, so it is executed directly and not added to the microtask, so the fifth output is: “j”;
6. When the second setTimeout is executed, it is found to be a macro task, and its callback is sent to the above macro task queue of setTimeout type, but the execution will be delayed for 1s.
7. Execute the whole code, the sixth output is “p”;
8. The macro task of the first event loop is completed (the whole code is considered as a macro task). There is only one Promise. Then microtask queue, which contains one task. There is also only one setTimeout macro task queue;
9. Let’s perform the first microtask of the event loop. Obviously, the seventh output is: “g”. The first event loop is complete;
10. Start the second event loop: Execute all tasks in the setTimeout type queue (macro task queue). Found some delay and some no delay, so the first implementation of the shortest delay macro task;
11. Run setTimeout. The eighth output is “I”.
12. Then execute setTimeout for 1s, so the ninth output after the delay of 1 second is: “k”;
The first argument in the Promise constructor is executed directly on new, so it will not enter any queue, so the tenth output is “L”, followed by a return statement, so the following code will not execute, and “m” will not be printed;
14. Then is found and pushed to the then queue that has already been executed. Note that since there is a micro-task THEN queue, all tasks in the queue will be executed (only one task at this time), so the eleventh output is “n”;
15. Delay setTimeout for 1s, so the twelfth output after two seconds is: “b”;
The first argument in the Promise constructor is executed directly on new, so it does not enter any queue, so the thirteenth output is “c”;
17. Then is found, and then is pushed to the queue that has already been executed. Note that since there is a micro-task THEN queue, all the tasks in the queue will be executed (there is only one task), so “D” is printed on the 14th.
Poof, that’s it. Did you understand that? That’s the way life is, you think you’ve passed a hard time and there’s a bright future ahead, but that’s the way it is, it’s going to give you another hard time and look at the code below, heh heh heh
async function async1() {
console.log("a");
await async2();
console.log("b");
}
async function async2() {
console.log( 'c');
}
console.log("d");
setTimeout(function () {
console.log("e");
},0);
async1();
new Promise(function (resolve) {
console.log("x");
resolve();
}).then(function () {
console.log("y");
});
console.log('z');
// Output result:
// d a c x z y b e
Copy the code
Don’t panic, don’t panic and listen to me slowly. Before saying async, we have to understand it. Ruan Yifeng teacher has a detailed introduction
Async
A, async
The use of async as a keyword in front of a function to indicate that the function is an asynchronous function, because async means asynchronous, and asynchronous function means that the execution of the function does not block the execution of the following code.
Let’s take a look at the async return value, see the following code:
async function testAsync() {
return "hello async";
}
const result = testAsync();
console.log(result);
// Output result:
// Promise { 'hello async' }
Copy the code
We see that sayNC prints a Promise object
Async functions (including function statements and function expressions) return a Promise object. If a function returns a direct Promise, async encapsulates the Promise object with promise.resolve ().
So what if we try no return value?
async function testAsync() {
console.log("hello async");
}
const result = testAsync();
console.log(result);
// Output result:
// hello async
// Promise { undefined }
Copy the code
An empty promis object is returned
Second, await
‘await’ is literally waiting. ‘await’ is waiting for an expression whose return value can be a Promise object or other value.
Note that await is not just used to wait for promises, it can wait for the result of any expression, so await is actually followed by ordinary function calls or direct quantities.
function getSomething() {
return "something";
}
async function testAsync() {
return Promise.resolve("hello async");
}
async function test() {
const v1 = await getSomething();
const v2 = await testAsync();
console.log(v1, v2);
}
test();
// Output result:
// something hello async
Copy the code
Await is an operator used to form an expression. The result of an await expression depends on what it is waiting for. If it is waiting for something other than a Promise, the result of an await expression is what it is waiting for.
content | describe |
---|---|
grammar | [return_value] = await expression; |
Expression | A Promise object or any value to wait for. |
Return value (return_value) | Returns the result of processing the Promise object. If you are waiting for something other than a Promise object, the value itself is returned |
But what happens when we get await?
Async functions can be thought of as multiple asynchronous operations wrapped as a Promise object, and await commands are syntactic sugar for internal THEN commands. When a function executes, it returns as soon as it encounters await, waits for the asynchronous operation to complete, and then executes the following statement in the function body.
That is,
Await test() in async; “, execute test() and get the return value (either a promise or some other value) to form await value; If value is a Promise object, the returned promise will be put into the task queue and await, and await will make the thread jump out of the async function and continue to execute the subsequent code. If value is something else but not added to the task queue, await also causes the thread to jump out of the async function and continue executing the following code.
With that in mind, let’s analyze the most difficult part of the code above:
Saync = sayNC; sayNC = sayNC; sayNC = sayNC;
2. When the first setTimeout is executed and it is found to be a macro task, a new macro task queue of type setTimeout will be created and the callback function of the current setTimeout will be sent to the newly established macro task queue, and it will be executed immediately when it is executed.
Async1 (); async1(); async1();
Async2 () is an async defined function, so “console.log(‘c’)” is executed. So the third output is: “c”;
5. Async2 returns a Promise, please note that the returned Promise will be queued and await, and await will cause the thread to exit async1 and continue execution!!
“X “; “x”; “x”; “x”;
Resolve (‘ z ‘); resolve (‘ z ‘); resolve (‘ z ‘)
8. Now that the call stack is empty, the event loop will fetch the task from the task queue and put it into the call stack.
The first task is a Promise that async1 has put in it. If it encounters resolve or reject, it will wait in the task queue and then jump out of async1 again to proceed to the next task.
10. The next task to execute is the resolve callback that new Promise put in, which executes then, so the sixth output is “y”;
Once the stack is empty again, the event loop moves on to the next task. The resolve or reject of the promise returned by async2 in async1 executes because Async2 doesn’t return anything. So the resolve argument is undefined;
12. At this point the await Promise has finished and returned the result, so we can proceed with the task after async1 which is “console.log(‘b’)”, so the seventh output is: “b”;
13. The stack is empty again and the setTimeout macro task is executed, so the eighth output is: “e”
Wow (@ο@) wow ~! Have you got it? I hope you understand this topic and will not be afraid of the interview any more! This thinking of a simple to write the following test solution steps did not expect to write so much at a draught, patience to read here small partners are very good, wish you in the technology of the road further and further!