This is the 18th day of my participation in the August Challenge

The preface

Recently, when LEARNING Vue source code $nextTick, I have a new understanding of task scheduling, including the use of promise to create a micro task this operation, so today we summarize the micro task related knowledge points, hoping to inspire you.

What are microtasks

Asynchronous tasks need to be managed properly, so ECMA specifies an internal queue, PromiseJob, which is called a microtask queue. The following is described in the specification.

  1. A queue is first-in, first-out: the first task to be queued is run first.
  2. Tasks in the task queue are executed only if there are no other tasks running in the JavaScript engine.

Or, simply put, when a promise is ready, its.then/catch/finally handlers are put into queues: but they are not executed immediately. When the JavaScript engine finishes executing the current code, it grabs the task from the queue and executes it.

example

let promise = Promise.resolve(); promise.then(() => alert("coolFish ready!" )); alert("code finished"); // This will be displayedCopy the code

As shown in the example above, alert(” Code finished”) is clearly in alert(“coolFish ready!” Alert (“coolFish ready! ) is placed in the microtask queue, which is executed when JS has finished executing the current code.

Control execution order:

Promise.resolve() .then(() => alert("coolFish ready!" )) .then(() => alert("code finished"));Copy the code

Now the code executes as expected.

An unprocessed rejection

If a promise error is not processed at the end of the microtask queue, an unprocessed rejection appears.

  1. False self-capture
let promise = Promise.reject(new Error("Promise Failed!" )); promise.catch(err => alert('caught')); // Will not run: error is handled window.addEventListener('unhandledrejection', event => alert(event.reason));Copy the code

The error was caught by promise.catch and the unhandledrejection event listener will not fire.

  1. Error not caught
let promise = Promise.reject(new Error("Promise Failed!" )); // Promise Failed! window.addEventListener('unhandledrejection', event => alert(event.reason));Copy the code

The error is not caught and the unhandledrejection event listens for it to fire.

  1. Put error capture into the macro task
let promise = Promise.reject(new Error("Promise Failed!" )); setTimeout(() => promise.catch(err => alert('caught')), 1000); // Error: Promise Failed! window.addEventListener('unhandledrejection', event => alert(event.reason))Copy the code

We find that the error is still triggered by the unhandledrejection event listener. Because error catching is performed after the microtask queue is empty, setTimeout puts error catching into the macro task. Therefore, the microtask will be triggered by the unHandledrejection listener before it is captured by a catch. Macro and micro task cases

SetTimeout (() => {// Call back a macro event console.log(' inner macro event 3')}, 0) console.log(' outermost macro event 1'); New Promise((resolve) => {console.log(' outmost macro event 2'); Resolve ()}).then(() => {console.log(' microevent 1'); }).then(()=>{console.log(' microevent 2')})Copy the code

The results are as follows

Outermost macro event 1 Outermost macro event 1 Microevent 1 Microevent 2 Inner macro event 3Copy the code

JS execution process is, execute a macro task, see if there is a micro task, execute it, and then execute the next macro task. Both macro and micro tasks have their own hierarchical relationships.