Javascript event loops are divided into two types: browser-side event loops and Node side event loops. This article is just an overview of my understanding of browser-side event loops.

preface

We all know that JavaScript is a single-threaded language, which means that only one task can be executed at a time, and then the next one can be executed. If the previous task is not completed, the later task will wait. Imagine a web request that takes a long time, and if all the tasks have to wait for the request to complete before they can continue, it’s obviously unreasonable and we don’t experience this situation in browsers (unless you’re making simultaneous Ajax requests), because JavaScript uses asynchronous scheduling.

There are three common asynchrony types in JavaScript: Ajax, DOM events (button click events, etc.), and timers (setTimeout, etc.).

For example

console.log("A");

setTimeout(() => {
  console.log("B");
}, 100);

console.log("C");
Copy the code

If you know something about asynchrony in the browser, you can answer “A C B”. Let’s analyze the event loop to sort out asynchrony in the browser and clarify the above problems.

Js is divided into three parts: Stack (main thread), WebAPIs, and Event Loop.

The browser executes in the following order:

1. Execute the main thread first, i.e

console.log("A");

setTimeout(() => {
  console.log("B");
}, 100);

console.log("C");
Copy the code

The program executes from the top down, but when it reaches setTimeout, it registers a WebAPIs event and does not execute the setTimeout callback. This callback function is asynchronous and will be executed according to the registered time after all programs in the main thread have finished executing.

2. When the main program finishes executing, execute the Event loop. Of course, the callback queue starts out empty. The event loop is an ‘infinite loop’ that checks the WebAPIs over and over again to see if there are any executable callback functions. If there are, it will put the callback functions into its own callback queue and execute them. If there are no callback functions, it will continue the next loop.

3. The browser listens for WebAPIs events. The timer event is triggered after 100ms, which notifies the Event loop that there is an executable callback.

A necessary condition for an event loop is that the task in the “task queue” will not be executed until the task in the execution stack completes. If the execution stack is in an endless state, there will be no task queue. Therefore, the settimeout parameter is not accurate. It should start at the end of the stack.

Settimeout also has a minimum time of 4ms, so when we write settimeout(function(){},0), the 0 is actually 4ms.

Microtasks and macro tasks

SetTimeout setImmediate MessageChannel setTimeout setImmediate Mediate MessageChannel setTimeout setImmediate MessageChannel Promise. Then MutationObserver Keep two things in mind:

  • A microtask is executed before a macro task. The contents in the execution stack are executed before the microtask is emptied
  • Remove microtasks each time you pick up a macro task, and then pick up the macro task again

The title

setTimeout(function(){
    console.log('setTimeout1');
    Promise.resolve().then(()=>{
        console.log('then1');
    });
},0)
Promise.resolve().then(()=>{
    console.log('then2');
    Promise.resolve().then(()=>{
        console.log('then3');
    })
    setTimeout(function(){
        console.log('setTimeout2');
    },0)
})
Copy the code
  • Microtask macro task appears at the same time, put the microtask into the execution queue first, if the stack is empty, execute then2 first. SetTimeout1 is placed in the macro task execution queue
  • After the execution of then2, the microtask then3 follows. Put THEN3 in the microtask queue.
  • Next setTimeout2 is added to the macro task queue.
  • If the stack is empty, execute then3.
  • After all the microtasks are executed, the macro task setTimeout1 and the microtask then1 are executed and placed in the microtask queue.
  • SetTimeout1 After the macro task is complete, empty the microtask queue again and execute then1
  • After all the microtasks are completed, execute the macro task setTimeout2. End of program.