Synchronous and asynchronous tasks
Single threaded JS tasks are divided into synchronous and asynchronous tasks. A synchronous task is a step-by-step execution of code that must wait for the previous task to complete before proceeding to the next. Just like crazy console.log() after alert(), the console won’t print anything until the popover closes.
If all the tasks become synchronous tasks, there will be a big problem, like waiting for someone else to send you data, you will definitely have to use a polling mechanism to determine whether he sent or not, and if he doesn’t send, you will have to wait for him to send, otherwise you won’t do the next step, which is definitely not feasible. So there’s the idea of an asynchronous task, registering an asynchronous operation as a callback, telling it to wait until it’s done and tell the program what the result is, and then the program can do something else.
The following is the execution diagram of synchronous and asynchronous tasks:
One conclusion we can draw from this graph is that synchronous tasks always precede asynchronous ones. Because the execution stack determines that the task is a synchronous task, it will execute it directly, while the asynchronous task will be added to the task queue (a first-in, first-out data structure) and will not be executed for the time being. Wait until the execution stack is empty, and then check whether the first task in the task queue has event callback. If there is event callback, execute it. After execution, remove the task queue (it should be certain that there will be event callback, otherwise asynchronous a lonely), and repeat until the task queue is empty.
Let’s do a little exercise
setTimeout(() = >{console.log("Asynchronous task"),0});
console.log("Synchronization task");
Copy the code
The output is
Asynchronous tasks are further subdivided into macro tasks and micro tasks
Further segmentation of asynchronous tasks, like going to a bank, requires a number to be numbered. It usually says something like, “Your number is XX and XX is in front of you.” “Or something like that.
Because the teller at the same time function to deal with a customer to deal with business, then each person to deal with business can be considered to be a macro task of the bank teller to exist, when the teller to deal with the current customer’s problems, choose to receive the next, broadcast the number, which is the beginning of the next macro task. So multiple macro tasks together can be thought of as having a task queue here, which is all of the customers in the current bank. Tasks in the queue is asynchronous operation has been completed, rather than the said registered an asynchronous task will be placed in the task queue, like numeral in the bank, if you don’t call to your time, then your current plate scrapped, teller would choose to skip to the next customer business processing, waiting for you to come back later also need to take a number
And a macro task in the process of execution, you can add some micro tasks, like at the counter for business, an old man in front of you may be in the deposit, after the deposit of this business, the teller will ask the old man there is no other need to deal with the business, then the old man thought: “Recently P2P thunder a little more, is it necessary to choose some stable financial management”, and then tell the teller said, to do some financial management business, at this time the teller certainly can’t tell the old man said: “you go on the back to take a number to queue up again.” So it would have been your turn to deal with the business, because the old man temporarily added “financial services” and postponed. Maybe the old man still wants to get another credit card after finishing his financial management? Or buy some commemorative coins? Whatever it is that the teller can handle for her, she will do it before dealing with your business. These can be considered microtasks. The next macro task will not be executed until the current micro task is completed.
Jiasm: juejin.cn/post/684490…
How a macro task is triggered
- A block of code in script
- setTimeout()
- setInterval()
- SetImmediate () (Non-standard, supported in IE and Node.js)
- Register event
The way microtasks are triggered
- Promise
- MutationObserver
- queueMicrotask()
Why microtasks
Microtasks are executed later than the code in the Call Stack(macro tasks) of the current event loop, and before the event handlers and timer callbacks.
The main reasons for using microtasks can be summarized as follows:
- Reduce user-perceived latency during operations
- Ensure consistency of task order, even when results or data are available synchronously
- Optimization of batch operations
Synchronization task, macro task and micro task animation execution process
console.log('global begin');
setTimeout(function timer1(){
queueMicrotask(()={
console.log('queueMicrotask')})console.log('timer1 invoke')},1800)
console.log('global end')
Copy the code
There is no doubt that synchronous tasks always take precedence over asynchronous tasks in the order of execution. After the synchronization task is executed, setTimeout() will generate a macro task, and the code segment will wait 1800ms before being put into the task queue. After the call stack is empty, Add the callback timer to the call stack, and the queueMicrotask() in Timer1 creates a microtask that waits for the macro task to complete.
The results can be clearly obtained.
Eventloop synchronizes, macros, and micros
Synchronous tasks are executed first without any doubt. Asynchronous tasks will be placed in the task queue according to the code sequence and executed by the main thread in accordance with the principle of micro first and then macro.
Code snippet with promise
New Promise(() => {}).then(), let’s look at this Promise code
The previous new Promise() part is a constructor, which is a synchronization task
The.then() is an asynchronous microtask, which is important
Code snippet with async await
Async /await is essentially a wrapper around promises, which are a type of microtask
So we can use await keyword like promise. then effect await can be followed by any JS expression. While “await” can wait for many types of things, its main purpose is to wait for the state of a Promise object to be resolved.
It should be noted that if the await is the promise object, the await will suspend the code behind the async function, and the synchronization code outside the async function will be executed first (note that the synchronization code inside the promise will be executed first), waiting for the promise object to fulfil, The resolve argument is returned as the result of an await expression, and the async function continues
Question makers please do the question (interview)
Didi Smart Zhongtai (11.26) front-end internship
setTimeout(function(){ console.log('1')});new Promise(function(resolve){
console.log('2');
for(var i = 0; i < 10000; i++)
{ i == 99 && resolve(); } }).then(function(){ console.log('3')});console.log('4');
Copy the code
Answer :2, 4, 3, 1
New Promise is a constructor, which is a synchronization task. After the synchronization task is executed, the setTimeout callback will macro the task queue, and the Promise’s then method will macro the task queue, and then output 3 1
Xiaomi front end internship experience
// Order of execution
async function async1() {
console.log('async1 start')
await async2();
console.log('async1 end')}async function async2() {
console.log('async2')}console.log('script start')
setTimeout(function () {
console.log('setTimeout')},0)
async1();
new Promise(
function (resolve) {
console.log('promise1')
resolve();
})
.then(
function () {
console.log('promise2')})console.log('script end')
Copy the code
The answer:
Script start async1 start setTimeout is printed and added to the macro task queue
Await = promise; aysnc2; aysnc2; await = await; aysnc2; aysnc2 So promise1,script end and then the rest of async1 aysnc1 end and then promise then and promise2 and then macro callback setTimeout