Explain the execution mechanism of JavaScript in detail

  • 2021-08-21 19:35:17
  • OfStack

1. About javascript

javascript is a single-threaded language, and Web Worker is proposed in the latest HTML5, but the core of javascript is single-threaded.

Why is js a single-threaded language? Because the original js was used to manipulate DOM elements in the browser validation form. If js is multithreaded and two threads simultaneously perform conflicting operations on one DOM, browser parsing cannot be performed.

The function of Web Worker is to create a multithreaded environment for JavaScript, allowing the main thread to create Worker threads and assign 1 task to the latter to run. While the main thread is running, the Worker thread runs in the background without interfering with each other. Wait until the Worker thread completes the calculation task, and then return the result to the main thread.

2. javascript event loop

When we call a method, js generates an execution environment (context) that corresponds to the method, also known as the execution context. The execution environment contains the private scope of the method, the direction of the upper scope, the parameters of the method, the variables defined in the scope, and the this object of the scope. When 1 series of methods are called in turn, because js is single-threaded, only one method can be executed in the same time, so these methods are queued in a single place. This place is called the execution stack.

Instead of waiting for an asynchronous event to return, the js engine suspends the event and continues with other tasks on the execution stack.

When an asynchronous event returns a result, js adds the event to a different queue from the current execution stack, which we call the event queue. Being put into the event queue does not immediately execute its callback, but waits for all tasks in the current execution stack to be completed. When the main thread is idle, the main thread will look for whether there are tasks in the event queue. If so, the main thread fetches the first event from it, puts the callback corresponding to this event into the execution stack, and then executes the synchronization code in it. This is repeated, thus forming an infinite cycle.

3. setTimeout

setTimeout this function, is after the specified time, the task to be executed is added to Event Queue, and because it is a single-threaded task to be executed one by one, if the previous task needs too long time, it can only wait.


setTimeout(() => {
 task()
},3000)

sleep(10000000)

The above code takes much more than 3 seconds to execute task (), and the execution process is as follows:

task () enters Event Table and registers, timing begins. Execute the sleep function, very slow, very slow, and the timing continues. After 3 seconds, the timing event timeout is completed, and task () enters Event Queue, but sleep has not been executed yet, so we have to wait. sleep finally finished execution, and task () finally entered the main thread execution from Event Queue.

   setTimeout(fn,0) It means that a task is specified to be executed at the earliest available idle time of the main thread, which means that it does not need to wait for many seconds, as long as all synchronous tasks in the main thread execution stack are completed and the stack is empty, it will be executed immediately.

4. setInterval

For execution order, setInterval will put registered functions into Event Queue every specified time. If the previous task takes too long, it also needs to wait.

The only point to note is that for setInterval (fn, ms), we already know that fn will not be executed once every ms second, but fn will enter Event Queue every ms second.

5. Promise and process. nextTick (callback)

Promise is a solution for asynchronous programming that is more reasonable and powerful than traditional solutions-callback functions and events.
The so-called Promise is simply a container, which holds the result of an event (usually an asynchronous operation) that will end in the future. Syntactically speaking, Promise is an object from which messages for asynchronous operations can be obtained. Promise provides API of System 1, and all kinds of asynchronous operations can be handled in the same way.

process. nextTick (callback) is similar to the "setTimeout" version of node. js, calling the callback callback function in the next loop of the event loop.

6. Macro and Micro Tasks

macro-task (Macro Tasks): Includes the overall code script, setTimeout, setInterval micro-task (micro-task): Promise. then, process. nextTick

Different types of tasks will enter the corresponding Event Queue, for example, setTimeout and setInterval will enter the same Event Queue.

The order of event loops determines the execution order of js code.

After entering the whole code (macro task), start the first loop. Then perform all the micro tasks. Then start from the macro task again, find one of the task queues to finish execution, and then execute all the micro tasks.


setTimeout(function() {
 console.log('setTimeout');
})

new Promise(function(resolve) {
 console.log('promise');
}).then(function() {
 console.log('then');
})

console.log('console');
This code enters the main thread as a macro task. If setTimeout is encountered first, register its callback function and distribute it to macro task Event Queue. Promise is encountered next, and new Promise executes immediately, because the code in the new Promise callback function is a synchronous task, and the then function is distributed to the micro task Event Queue. Encountered console. log (), execute immediately. Ok, the whole code script ends as the first macro task. Let's see what micro tasks are there. We found that then is executed in the micro-task Event Queue. The first event loop is over, and we begin the second loop, starting with the macro task Event Queue, of course. We found the callback function corresponding to setTimeout in the macro task Event Queue and executed it immediately. End.

7. async await

1. What does 1. async do?

A function with the async keyword, which makes the return value of your function must be an promise object.

That is, if the async keyword function does not return promise, it is automatically wrapped with Promise. resolve (). If the async keyword function explicitly returns promise, then the promise you returned will prevail.

2. What is await waiting for?

await and so on are the results of the "expression" on the right. That is, if the right side is a function, then the return value of the function is "the result of the expression". If on the right is a 'hello' or something, the result of the expression is' hello '.

3. await What did you do after waiting?

The result of the expression on the right side of await is what await has to wait for. After that, for await, there are two situations:

Is not an promise object Is an promise object

If it is not promise, await will block the following code. First, execute the synchronization code outside async. After the synchronization code is executed, go back to the inside of async and take this non-promise as the result of await expression.

If it waits for an promise object, await also pauses the code after async, executes the synchronization code outside async first, waits for Promise object fulfilled, and then takes the parameters of resolve as the operation result of await expression.

4. Examples


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');
This code enters the main thread as a macro task. Print out script start first. The function async1 is then executed. Print out async1 start, execute to await, execute function async2, print out async2. At this point, await will block the code behind async1, and the synchronization code outside async1 will be executed first. setTimeout puts the macro task into the event loop. Then execute to Promise, print out promise1, promise. then into the event loop micro-task. Then print script end. Now that the synchronization code outside async1 is finished, go back inside async1 and print out async1 end. After the whole code is executed, execute the micro-task promise. then and print out promise2. Finally, execute the macro task setTimeout and print setTimeout.

So the order of execution of this code is: script start- > async1 start - > async2 - > promise1 - > script end - > async1 end - > promise2 - > setTimeout

The above is the detailed explanation of JavaScript execution mechanism details, more information about JavaScript execution mechanism please pay attention to other related articles on this site!


Related articles: