preface

A few days ago, I encountered callback hell in the project, but I didn’t use Promise when I started writing this project. I only knew it could be used to solve callback hell, so I used all callback functions to solve it. I read the book “in-depth understanding of ES6” to learn the Promise, in the usage and function of the very detailed, but in the principle of how to say, so use when there are a lot of questions, so on the Internet to find an article to realize the Promise to understand the principle of Promise.

Reference links:www.mattgreer.org/articles/pr…

First, the simplest usage

new Promise( (resolve, reject) = > {
    resolve(42)
}).then( result= > {
    console.log(result)
})

// Console output
/ / 42
Copy the code

This is the simplest use of a Promise (let’s not talk about reject, assume all actions are accepted resolve). I’m glad I’m finally using Promise, but I’ve had some problems with it. Before I say anything about my problems, let’s talk about the callback of a function

The callback function

In JS, function A is called a callback when it is passed as an argument to another function B. Function A is called from the body of function B, and function A is called back by function B.

OK, now that we know what a callback is, can I say what I’m asking

Two, my question —resolvethen

Let’s first analyze how many callbacks there are in the simplest example above. Let me rewrite the above code:

// Instead of using the arrow function, use the variable reject
let fn1 = function (resolve) {
    resolve(42)}let fn2 = function (result) {
    console.log(result)
}

new Promise(fn1).then(fn2)  / / 42
Copy the code

The new Promise(fn1).then(fn2) line makes it clear that there are two callbacks, but that’s not all. Look at fn1

let fn1 = function (resolve) {
    // resolve is a callback function
    resolve(42)}Copy the code

So now our callback function looks like this:

Fn1 (resolve) is passed to the Promise. Then () is called after the Promise object is created, and fn2 () is passed to the THEN method. (A little bit of the new operator is involved here.)

Well, after analyzing the callback function, I’m starting to get confused:

  • Question 1: When will it be calledfn1I don’t even know
  • Question 2: I didn’t give itfn1Call function
  • Question 3: Just pretend I knowfn1When was it called? Why is it calledfn1callresolveWhy does it look like the call I passed tothenThe callback function offn2?
  • Ah?

Three, the implementation principle

Finally, back to business, to solve my above question.

In the first reference article, the author implemented a fairly complete Promise, which is a bit long, so I’ll just take the principles that can be used to implement the simplest promises written above.

function Promise(fn) {
  var state = 'pending';        // Promise current state
  var value;                    // The value saved when the Promise was in the accepted state. This is the result
  var deferred;                 // Defer the execution of the function.

  function resolve(newValue) {  // The function to execute after a Promise is accepted
    value = newValue;           // Save the result
    state = 'resolved';         // Change the status to Resolved

    if(deferred) {              // If deffred is not undefined, there is already a reference to the function
      handle(deferred);         // Pass deffred to handle}}/* * The handler function that is called when the user calls the then function and so on explains */
  function handle(onResolved) {
    if(state === 'pending') {   // Determine the current state. If it is a padding state, it is still in the initial state
      deferred = onResolved;    // Save the onResolved callback and execute it later
      return;                   // padding state does not execute the following statement
    }

    onResolved(value);          // If it is not the padding state, call onResolved and pass the result to the callback
  }

  /* * it is a function that passes a parameter, so it is a function that passes a parameter. OnResolved is a callback */
  this.then = function(onResolved) {
    handle(onResolved);         // Whenever the then function is called, pass onResolved (fn2 in the example) to handle
  };
  
  /* * Return fn1; /* return fn1; /* return fn1; The callback passed when fn1 is called is Promise's internal function resolve */
  fn(resolve);
}
Copy the code

Question 3 Solution:

See FN’s notes for solutions to the first two questions

So when we call then with the Promise object, we pass fN2, so onResolved is going to FN2, and then onResolved is going to handle, and then onResolved is going to be called in Handle, so Fn2 is going to be called in Handle.

Now we know that Fn2 is called in Handle. Then look at where handle is called:

Since there are no asynchronous operations in this example, the padding case is not considered:

The handle function is called in the then function

Let’s go back to the simplest Promise:

let fn1 = function (resolve) {
    resolve(42)}let fn2 = function (result) {
    console.log(result)
}

new Promise(fn1).then(fn2)  / / 42
Copy the code

1. Performnew Promise(fn1)What did he do?

When the program executes to a new Promise, the Promise statement fn(resolve) executes immediately, calls the callback we passed fn1, and returns a value called resolve, (The resolve argument refers to the resolve() function in the Promise object, and we didn’t write any asynchronous operations in this case, so everything is almost synchronous). We immediately call the resolve callback and pass it a value of 42(newValue), state is set to ‘resolved’, and the new Promise is complete. To summarize: Our example does not have an asynchronous operation, so resolve will be called with a new Promise and the state changed to ‘resolved’.

2. Performthen(fn2)What did he do?

In this example, the then function is called immediately after the Promise object is created, passing in a callback function called fn2. When calling then, then calls the handle of the Promise object and points onResolved to Fn2. As status was changed to ‘resolved’ in the new Promise, the if statement in the handle body will not hold. The onResolved(value) will be executed and the value from the new Promise will be passed in, so fn2 will be called back by Handle. Handle is called when we call THEN, and the new Promise value is passed back to the fn2 callback

So far, problem number three has been solved.

Conclusion question three:

When FN was called, it returned the Promise’s internal function resolve to FN1, which was received by fN1’s resolve parameter. Therefore, the resolve called in fN1’s method body actually refers to Promise’s internal function resolve, but we passed it the value 42. Saved in value by Promise’s resolve function. When calling then, value is passed out by Handle to Fn2.

Finally solved the problem!!

It’s pretty easy to understand what the three states of promises do, and how to implement serial promises and reject. There’s a lot more to it, but I won’t write it.

Four, the use and understanding of Promise involved in the knowledge points

  • The new keyword creates an object
  • This keyword
  • Prototype chain
  • Asynchrony between JS and browser
  • event loop