Deep learning promise

Time:2020-8-2

preface

If you read a lot of promise documents and resources, but find that you always can’t master the essence of promise, maybe you can take a look at this article of mine, which may be helpful for you.

JS operation mechanism

Before learning to use promise, you need to understand the operating mechanism of JS.

The concurrency model of JavaScript is based on “event loop”, which is quite different from that in other languages such as C or Java.

Visual description

Deep learning promise

Stack

The function call forms a stack frame.

function foo(b) {
  var a = 10;
  return a + b + 11;
}

function bar(x) {
  var y = 3;
  return foo(x * y);
}

console.log(bar(7));

When bar is called, the first frame is created, which contains the bar’s parameters and local variables. When bar calls foo, the second frame is created and pressed on top of the first frame, which contains foo parameters and local variables. When foo returns, the top frame is popped out of the stack (the remaining call frame of the bar function). When bar returns, the stack is empty.

heap

Objects are allocated in a heap to represent a large area of unstructured memory.

queue

A JavaScript runtime contains a message queue to be processed. Each message is associated with a function. When the stack has enough memory, a message is taken from the queue for processing. This process involves calling the function associated with the message (and thus creating an initial stack frame). When the stack is empty again, it means the end of message processing.

event loop

It is called an event loop because it is often implemented in a way similar to the following:

while (queue.waitForMessage()) {
  queue.processNextMessage();
}

If there is no current message queue.waitForMessage Will wait for the synchronization message to arrive.

Resources: concurrency model and event loop

Promise review

Promise is actually a function whose instance is an irreversible state machine. You can usually create an instance of promise in the following ways.

Using new

const promise = new Promise((resolve, reject) => {
    ......
    resolve(xxx)
    ......
});

Use static API

Promise.resolve, Promise.reject, Promise.all, Promise.raceAfter the static methods provided by the are executed, a promise will also be returned.

const promise = Promise.resolve('complete');
// promise instanceof Promise  => true

Adding a callback function returns a promise

When we use then, catch and finally add a callback function in a promise instance, we will return a promise.

const promise = Promise.resolve('complete').then((val)=> {
    console.log(val) // complete
})
// promise instanceof Promise  => true

Instance status of promise:

  • Pending: initial state, which is neither successful nor failed.
  • Fulfilled: means the operation completed successfully.
  • Rejected: means the operation failed.

When the instance status of promise is changed from pending = > fulfilled, the first function registered in then will be triggered.
When the instance state of promise is pending = > rejected, the second function registered in then or the function registered in catch will be triggered.
When the instance state of promise changes, the functions registered finally will be triggered.

Promise operation mechanism

Understanding the operating mechanism of promise can help us better use promise. The following figure depicts the operation mechanism of promise based on the implementation of ES6 promise.

Deep learning promise

We have already introduced the running mechanism of JS. JS is based on the event loop. When the message queue of JS operation is cleared, it will go to the asynchronous queue to get messages and join the JS running queue. When promise is available, all promise run queues will be added to JS run message queue before getting asynchronous queue messages. During this run, if the promise run queue adds a new callback function, the promise run queue will be re added to the message queue of JS operation. Until the promise run queue and JS run message queue are cleared, messages will not be obtained from the asynchronous queue. That’s the guaranteePromise’s callback functions precede asynchronous calls。 However, during development, you also need to prevent entering the promise callback trap, as shown below

function bar() {
    Promise.resolve('resolve').then((val) => {
        console.log(val);
        bar();
    })
}
bar()
console.log('continue');
setTimeout(() => {console.log('setTimeout')});
// continue resolve resolve resolve resolve ......

In the example above, setTimeout will never be output.

PromiseAny state (pending, resolved, rejected) of an instance can use then, catch, finally to register (add) callback functions. The difference is that the promise instance in the pending state will store these callback functions internally. When the state changes, all the related callback functions will be pushed to the promise running queue. The instances in the resolved and rejected States will immediately push the related functions to the run queue of the promise without waiting.

var callback;
var promise = new Promise((resolve) => {
   callback = resolve;
})

promise.then(() => {console.log('1')});
Promise.resolve('2').then((val) => {console.log(val)}); 
callback();
//Output 2 1

In the example abovepromiseThe registered functions will not be pushed into the promise running queue until the callback is executed, so the registered functions will run later.

When the instance state of promise is resolved. Only the functions registered by resolve and finally in then will be added to promise’s running queue. And the order in which they are executed depends only on the order in which they are added.

var promise = new Promise((resolve, reject) => {
    resolve('ok');
})

promise.finally(() => {
   console.log('finally');
});
promise.then((val) => {
  console.log(val);
});
promise.catch(() => {
  console.log('catch');
});

// finally ok

Obviously, if finally appears before OK, the functions registered by the catch will not be pushed to the promise run queue and will not be executed.

When the instance status of project is rejected. The functions registered by reject, catch and finally in then will be added to the run queue of project. And the order in which they are executed depends only on the order in which they are added.

var promise  = Promise.reject('reject');
promise.finally(() => {console.log('finally')}); 
promise.catch(() => {console.log('catch')}); 
promise.then(() => {console.log('ok')}, (val) => {console.log(val)});
// finally catch reject

The above is personal exploration and learning about promise, supplemented by another article, in-depth study of promise call chain.

Recommended Today

ASP.NET Example of core MVC getting the parameters of the request

preface An HTTP request is a standard IO operation. The request is I, which is the input; the responsive o is the output. Any web development framework is actually doing these two things Accept the request and parse to get the parameters Render according to the parameters and output the response content So let’s learn […]