Before understanding macro tasks and micro tasks, we need to know some basic concepts of JS running mechanism
JS operation mechanism
- JS is single threaded execution
function person() { play() } function play() { swim() } function swim() { throw new Error('error') } person()
A man is going to play and then go swimming. He is in danger
When reporting an error, follow the principle of first in and last out. This is the characteristic of the stack - that is, the execution stack
2. JS generally runs in the browser or Node
3. How does JS work?
Event cycle mechanism
In the Event Loop, each cycle is called a tick. The tasks of each tick are as follows:
- The execution stack selects the macro task (generally script) that enters the queue first, and executes its synchronization code until the end;
- Check whether there is a micro task. If yes, it will be executed to the micro task queue is empty;
- If the host is a browser, the page may be rendered;
- Start the next round of tick and execute the asynchronous code (setTimeout and other callbacks) in the macro task.
Expand $nextTick in Vue
vm.$nextTick accepts a callback function as a parameter to delay the callback until after the next DOM update cycle.
This API is implemented based on event loops.
"Next DOM update cycle" means to update the DOM the next time the micro task executes, and vm.$nextTick means to add the callback function to the micro task (it will be degraded to a macro task in special cases).
For more Node.js event loops, see: Node.js event loop, timer and process.nextTick()
What are macro tasks and micro tasks
Macro task and micro task
Basic concepts
- In the ES6 specification, microtask is called jobs and macrotask is called task
- Macro tasks are initiated by the host, while micro tasks are initiated by JavaScript itself.
- Macro is a term for batch processing
Macro task (macro) | micro task | |
---|---|---|
Who initiated it | host | JavaScript |
Specific events | script, setTimeout, setInterval, I/O, etc | . then, catch, finally process.nextTick (Node.js), etc. (new Promise is not a micro task) |
Will it trigger a new round of Tick | meeting | can't |
Execution procedure:
- Each macro task is individually associated with a micro task queue
- The execution sequence is: main thread > micro task > macro task [popular memory method: start with small things]
Generation of micro tasks
- In ES3 and previous versions, JavaScript itself does not have the ability to initiate asynchronous requests, so there is no micro task.
- After ES5, Promise was introduced into JavaScript, so that the JavaScript engine itself can initiate asynchronous tasks without a browser.
[problem] both macro task and micro task can operate asynchronously. What is the problem to be solved by micro task?
[answer] in order to solve the problem of too long waiting time for asynchronous callback when there are too many main thread tasks, an effective trade-off can be made between real-time and efficiency
Example
console.log(11111) setTimeout(() => { console.log(22222) }) new Promise(resolve => { resolve() console.log(3333) }).then(() => { console.log(44444) }).finally(() => { console.log(55555) }) console.log(66666)
Output: 136452
Resolution:
- Sequential execution, output 1
- Execute the setTimeout macro application and enter the macro task queue
- Execute Promise output 3
- . then. Finally the micro application enters the micro application queue (this is related to the event loop mechanism)
- Sequential execution, output 6
- The micro application executes faster than the macro application, so output 451
Speaking of Promise, I can't help thinking of async await in Vue, which turns asynchronous into synchronous
On async await
console.log('script start') async function async1() { await async2() console.log('async1 end') } async function async2() { console.log('async2 end') } async1() setTimeout(function() { console.log('setTimeout') }, 0) new Promise(resolve => { console.log('Promise') resolve() }) .then(function() { console.log('promise1') }) .then(function() { console.log('promise2') }) console.log('script end')
What is your expected answer? The correct answer is as follows:
script start async2 end Promise script end async1 end promise1 promise2 setTimeout
The most unexpected position for you should be async1 end. Why is he in this position again?
async function async1() { await async2() console.log('async1 end') } async function async2() { console.log('async2 end') } async1()
To ES5:
new Promise((resolve, reject) => { // console.log('async2 end') async2() ... }).then(() => { // Execute the statement after the async1() function await console.log('async1 end') })
I can't help seeing the output in the micro task. then
Recommended articles
What are macro tasks and micro tasks?
Node.js event loop, timer and process.nextTick()