directory

  1. Why is JS single threaded
  2. [Asynchronous task] Macro task and micro task
  3. code
  4. Event cycle flow chart
  5. What is an Event loop
  6. Tasks and queues in JS
  7. Execution stack and event queue
  8. [Asynchronous task] Macro task and micro task
  9. Nine summary

Example scenario: For example, I am writing code (this is a synchronous task) -> I am hungry and order a takeout (I am still writing code in the synchronous task before the takeout arrives) -> Takeout arrives food + drinks etc (micro task in asynchronous task) -> Continue writing code in synchronous task

  1. Synchronize code => micro task => macro task

oneWhy is JS single threadedAsynchronous tasksCause of occurrence

JS is a single-threaded scripting language.

So why does JS have to be single-threaded? Wouldn’t it be much more efficient to do something like multithreading? The answer, of course, is no. JS was created for the browser, and the user must have a lot of interaction with the browser, and will manipulate the DOM in the process of interaction. If you have multiple threads, one thread has to add and one thread has to delete, you have a problem.

For browsers, a single thread is always more rigorous than a multi-thread, so there is a problem. If an operation takes a lot of request time or the code does a lot of calculations, our page will freeze because the previous code will never finish executing and will not run to the next code.

Two [asynchronous task] macro task, micro task

See article 8 below

  • Macro task:script,setTimeout,setInterval,I/OThe Promise constructor body before the statement THEN.
  • Micro tasks:Process.nextTick,Promise.then,MutationObserve.

aMacro taskThe command is displayed after the command is executedMicrotask queueDetermines whether to execute for emptyMicro tasksLet’s go to the next oneMacro task.

Three code

1) not


console.log('I'm script start! ')

setTimeout(() = > {
    console.log('I am a setTimeout! ')},0)

new Promise((resolve) = >{
    console.log('I'm the Promise! ')
    resolve()
}).then(() = >{
    console.log('I'm Promise. Then! ')})console.log('I'm script over! ')

Copy the code

A piece of code will not execute a macro task until all microtasks have been executed!!

The execution result

2) demo2

console.log('I'm script start! ')

setTimeout(() = > {
    console.log('I am a setTimeout! ')},0)

new Promise((resolve) = >{
    console.log('I'm the Promise! ')
    resolve()
}).then(() = >{
    console.log('I'm Promise. Then! ')})console.log('I'm script over! ')

new Promise((resolve) = >{
    console.log('I'm Promise 1')
    resolve()
}).then(() = >{
    console.log('then 1')
}).then(() = >{
    console.log('then 2')
}).then(() = >{
    console.log('then 3')})Copy the code

Perform synchronization tasks in script first, console.log, Promise. When setTimeout is encountered, push it to the event list to check whether the asynchronous code execution has ended (.then). Then is the microtask, and execute the next macro task setTimeout when the microtask is completed.

The execution result

3) demo3

Join the async await

Async /await is essentially a syntactic sugar for Generator and returns a Promise object.

Await must be used inside async function. On encountering an await, the code pauses and only resumes execution after the asynchronous operation has completed.

        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');


Copy the code

The execution result

Pay attention to

The code after await in the figure above is executed directly. So we change await to Promise

await async2();
// Why is the lower console not executed in this loop?
console.log('async1 end');
Copy the code
        console.log('script start');

        async function async1() {
            new Promise(res= >{
                async2()
                res()
            }).then(() = >{
                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');


Copy the code

This requires a clear understanding of the order in which synchronous, asynchronous, macro and micro tasks are executed.

  • 1. Execute the synchronization code first.scriptBelongs to a macro task.
  • 2. After all synchronous code is executed, check whether asynchronous code needs to be executed.
  • 3. Perform microtasks in asynchronous code, if any.
  • 4. After all microtasks are executed, the first round of Event Loop will end.
  • 5. Start a new Event Loop to execute the macro task in the asynchronous task.

Flow chart of event cycle

What is event Loop

Event loop is also called event loop, which is used to coordinate events, user interaction, script, rendering, and networking. A mechanism that results from the work of user agents.

Six JS running mechanism [single thread]

6.1 Single-threaded JavaScript

One of the hallmarks of the JavaScript language is single threading, which means doing the same thing at the same time. This is based on the execution environment of JS, because in the browser, there are many DOM operations, if the operation of a DOM at the same time, it is easy to cause chaos, so in order to avoid the occurrence of the operation of the same DOM at the same time, JS chooses only one main thread to execute the code, to ensure the consistency of program execution. The single-threaded feature also applies to Node.

6.2 Tasks and queues in JS

  • Synchronization task [Main thread]
  • Asynchronous task [Task Queue]

For example:Synchronization task -> Multiple Ajax requests -> Macro task -> Micro tasks -> …

JavaScript is single-threaded, which means that all tasks need to be queued before the next task can be executed, but because IO devices are slow (such as Ajax reading data from the network), they have to wait for the results to return before they can continue. So there are two kinds of tasks to deal with, synchronous and asynchronous tasks. A synchronous task is a task that is queued on the main thread. The subsequent tasks are executed only after the previous tasks are completed. Asynchronous tasks enter a task queue instead of the main thread. Tasks in the main thread can continue to be executed later, and asynchronous tasks in the task queue will notify the main thread when they are finished.

Execution stack and event queue

As javascript code executes, different variables are stored in different locations in memory: the heap and stack. There are some objects in the heap. The stack holds some basic type variables and Pointers to objects. When all synchronization tasks are executed on the main thread, these tasks are arranged in a single place, forming an execution stack

When the browser JS engine parses this code, it adds the synchronous tasks to the execution stack in sequence. When an asynchronous task is encountered, it does not wait for the return result of the asynchronous task before executing the subsequent tasks. Instead, it suspends the asynchronous task and continues to execute the synchronous task. Add callback events of asynchronous tasks to a Task Queue. Tasks in this Queue are not executed immediately, but are executed sequentially after all synchronous tasks are completed.

An Event Loop is formed by executing synchronization tasks in sequence, executing Event queues after completion, and then executing synchronization tasks after completion.

Macro Task and Micro Task

  • Macro task
  • Micro tasks

Asynchronous tasks are divided into macro tasks and micro tasks. Micro tasks are executed in the order of microTask >macroTask rather than in the order of event queue. All microtasks in the queue are executed before macroTask is executed

Classification of macro and micro tasks

  • MacroTask: Script (overall code), setTimeout, setInterval, setImmediate (node only), I/O, UI rendering
  • MicroTask: Process. nextTick (node only), Promises, Object.observe(deprecation), MutationObserver
// For example
setTimeout(() = >{
    console.log(1)})Promise.resolve().then(function() {
    console.log(2)})console.log(3)

// The result is 3, 2, 1
// This is because the order of the event loop is: synchronous code => microtasks => macro tasks

Copy the code

Nine summary

Example scenario: For example, I am writing code (this is a synchronous task) -> I am hungry and order a takeout (I am still writing code in the synchronous task before the takeout arrives) -> Takeout arrives food + drinks etc (micro task in asynchronous task) -> Continue writing code in synchronous task

  • Synchronize code => micro task => macro task
  • Synchronization code -> All microtasks (in asynchronous code)-> Next round of Event LoopMacro task.
  • Synchronous task [main thread], asynchronous task [Task Queue]

other

  • Resolved for ES6 Promise in depth
  • Juejin. Cn/post / 684490…