How Javascript works: Event loop

Reprint: original link

What is an event loop?

We start with a strange claim - while asynchronous JavaScript code (like setTimeout me) is allowed, JavaScript itself never actually had any direct concept of async built into it until ES6. The JavaScript engine never does anything other than execute a single block of the program at any given moment.

So, who tells the JS engine to execute your block? In fact, the JS engine does not run in isolation, but in a hosted environment, which for most developers is a typical web browser or Node.js. In fact, today, JavaScript is embedded in everything from robots to light bulbs. Each individual device represents a different type of hosting environment for JS Engine.

Common across all environments is a built-in mechanism called an event loop that handles the execution of multiple blocks in a program each time JS Engine is called

This means that a JS engine is just an on-demand execution environment for any arbitrary JS code. The time to schedule the event (JS code execution) is the surrounding environment.

So, for example, when your JavaScript program makes an Ajax request to get some data from the server, you set the "response" code ("callback") in the function, and the JS engine tells the hosting environment: "Hey, I'm for now Pause execution, but as soon as you complete that network request and have some data, call this function back."

The browser is then set up to listen for responses from the network, and will schedule a callback function to execute by inserting it into the event loop when there is something that needs to be returned to you. Let's look at the image below:

1_FA9NGxNB6-v1oI2qGEtlRQ.png

What are these Web APIs? Essentially, they are threads that you don't have access to, and you can call on them. They are part of the browser that initiates concurrency. If you are a Node.js developer, these are C++ APIs.

So what exactly is an event loop?

1_KGBiAxjeD9JT2j6KDo0zUg.png

The event loop has a simple job - listening to the Call Stack and Callback Queue. If the Call Stack is empty, the Event Loop will grab the first event from the queue and push it into the Call Stack, effectively running the event. Such iterations are called ticks in the event loop and each event is just a function callback.

console.log('Hi');
setTimeout(function cb1() { 
    console.log('cb1');
}, 5000);
console.log('Bye');
复制代码

Let's "execute" this code and see what happens:

  1. Status is clear. The browser console is cleared and the call stack is empty.

1.png

  1. console.log('Hi') is added to the call stack

2.png

  1. console.log('Hi') is executed.

3.png

  1. console.log('Hi') is removed from the Call Stack.

4.png

  1. setTimeout(function cb1() { ... }) is added to the Call Stack.

5.png

  1. setTimeout(function cb1() { ... }) executes. The browser will create the timer as part of the Web API. It handles the countdown for you.

6.png

  1. setTimeout(function cb1() { ... }) itself has completed and has been removed from the Call Stack.

7.png

  1. console.log('Bye') is added to the Call Stack.

8.png

  1. console.log('Bye') executes.

9.png

  1. console.log('Bye') is removed from the Call Stack.

10.png

  1. After at least 5000ms, the timer finishes and pushes the cb1 callback to the "Callback Queue".

11.png

  1. Event loop cb1 gets from the Callback Queue and pushes it to the Call Stack.

12.png

  1. cb1 executes and adds console.log('cb1') to the Call Stack.

13.png

  1. console.log('cb1') executes.

14.png

  1. console.log('cb1') is removed from the Call Stack.

15.png

  1. cb1 is removed from the Call Stack.

16.png

Quick recap:

1_TozSrkk92l8ho6d8JxqF_w.gif

Interestingly, ES6 specifies how the event loop works, which means it's technically under the purview of the JS engine, which no longer just acts as the hosting environment. One of the main reasons for this change was the introduction of Promises in ES6, as the latter required access to direct, fine-grained control over scheduling operations on the event loop queue (which we'll discuss in detail later)

How setTimeout(...) works

It's important to note that setTimeout(...) does not automatically place the callback in the event loop queue. It sets a timer. When the timer expires, the environment will put your callback into the event loop so that some future tick will pick it up and execute it. Take a look at this code:

setTimeout(myCallback, 1000);

It doesn't mean that myCallback will execute in 1,000ms, but myCallback will add it to the event loop queue in 1,000ms. However, there may be other events added earlier in the queue - your callbacks will have to wait.

See the code below:

setTimeout(function() {
    console.log('callback');
}, 0);
console.log('Bye');
复制代码

Although the wait time is set to 0ms, the result in the browser console will be the following:

Hi
Bye
callback
复制代码

Guess you like

Origin juejin.im/post/6950488674488287246