Promise me, I must understand this time! Promise. (Small snack async / await, a better solution based on Promise)

Promise

Before the Promise, we handled an asynchronous network request, something like this:

// The request represents an asynchronous network call. 
// The request result represents the response to the network request. 
Request 1 ( function (request result 1) { 
    process request result 1 
})

It looks pretty good.
However, the requirements have changed, we need to execute the second network request based on the result of the first network request, the code is probably as follows:

Request 1 ( function (request result 1) { 
    Request 2 ( function (request result 2) { 
        process request result 2 
    }) 
})

It doesn't look complicated.
but. . The demand is endless, so the following code appears:

Request 1 ( function (Request result 1) { 
    Request 2 ( function (Request result 2) { 
        Request 3 ( function (Request result 3) { 
            Request 4 ( function (Request result 4) { 
                Request 5 ( function (Request result 5) { 
                    Request 6 ( function (Request result 3) { 
                        ... 
                    }) 
                }) 
            }) 
        }) 
    }) 
})

This time dumbfounded. . . The infamous callback hell appeared.

What's worse, we basically have to deal with the results of each request, the code will be more bloated, in a team, code review and subsequent maintenance will be a very painful process.

The negative effects of callback hell are as follows:

  • The code is bloated.
  • Poor readability.
  • The coupling is too high and the maintainability is poor.
  • Code reuse is poor.
  • It is easy to breed bugs.
  • Exceptions can only be handled in callbacks.

When something goes wrong, someone will naturally find a way. At this time, some people have thought about whether they can use a more friendly code organization method to solve the problem of asynchronous nesting.

let request result 1 = request 1 (); 
let request result 2 = request 2 (request result 1); 
let request result 3 = request 3 (request result 2); 
let request result 4 = request 2 (request result 3); 
let Request result 5 = Request 3 (Request result 4);

Synchronous writing similar to the above. So the Promise specification was born, and there are many implementations in the industry to solve the pain points of callback hell. For example, the industry-famous Q and bluebird, bluebird even claim to be the fastest library.

What is a promise

Promise is a solution for asynchronous programming, which is more reasonable and powerful than traditional asynchronous solutions [callback function] and [event]. It has now been incorporated into the specification by ES6.

Code writing comparison

Still using the above network request example, let's take a look at the conventional way of writing Promises:

new Promise (request 1) 
    .then (request 2 (request result 1)) 
    .then (request 3 (request result 2)) 
    .then (request 4 (request result 3)) 
    .then (request 5 (request result 4)) 
    . catch (handling exceptions (exception information))

Compare this to the callback style above. It is not difficult to find that Promise is written more intuitively, and can catch abnormal information of asynchronous functions in the outer layer.

API

Promises commonly used APIs are as follows:

  • Promise.resolve(value)
Class method, this method returns a Promise object parsed by value value
 1. If the value is a thenable (ie with the then method), the returned Promise object will "follow" the thenable object, adopting its final state (referring to its final state (referring to resolved / rejected / pending / settled) 
2. If the value passed in is a Promise object itself, the object is returned as the return value of the Promise.resolve method.
3. In other cases, return a Promise object with this value as the success status.

The above is the explanation of the resolve method. When different types of value are passed in, the return result is also different. This API is more important. It is recommended that you get familiar with it by practicing some small examples and cooperate with the above explanation. Here are some small examples:

// If the value passed in is itself a Promise object, the object is returned as the return value of the Promise.resolve method.  
function fn (resolve) { 
    setTimeout ( function () { 
        resolve ( 123 ); 
    }, 3000 ); 
} 
let p0 = new Promise (fn); 
let p1 = Promise.resolve (p0);
 // Return to true, return Promise is the Promise object that enters the parameter. 
console.log (p0 === p1);

Pass in the thenable object, and return the Promise object to follow the final state of the thenable object.

The concept of Thenable is mentioned in ES6 Promises. In short, it is a very similar Promise. The simplest example is jQuery.ajax, and its return value is thenable object. 
But keep in mind that it is not necessary to use it as a Promise object as long as the then method is implemented.
// If the value passed in is itself a thenable object, the returned promise object will follow the state of the thenable object. 
let promise = Promise.resolve ($. ajax ('/ test / test.json')); // => promise object 
promise.then ( function (value) { 
   console.log (value); 
});

Returns a Promise object whose state has become resolved.

let p1 = Promise.resolve (123 ); 
 // Print p1 You can see that p1 is a Promise object with the status set to resolved 
console.log (p1)
  • Promise.reject

Class methods, and the only difference with resolve is that the status of the returned promise object is rejected.

  • Promise.prototype.then

Instance method, register a callback function for Promise, function form: fn (vlaue) {}, value is the return result of the previous task, the function in then must return a result or a new Promise object, then only then Callback reception.

  • Promise.prototype.catch

Instance method, catch exception, function form: fn (err) {}, err is the exception information thrown by the callback before catch registration.

  • Promise.race

In the class method, multiple Promise tasks are executed at the same time, and the result of the Promise task that is the first to execute is returned, regardless of whether the Promise result is successful or failed. .

  • Promise.all

Class method, multiple Promise tasks are executed simultaneously.
If all are successfully executed, the execution results of all Promise tasks are returned in an array. If there is a Promise task rejected, only the result of the rejected task is returned.

  • ...

The above are the commonly used APIs of Promises. After mastering these, we can use Promises proficiently.

Be sure to practice more and be proficient, otherwise a half-knowledge will be stretched during the interview.

How to understand Promises

 

In order to facilitate the understanding of Promises, in addition to more practice, the best way is to be able to connect the Promise mechanism with real-life examples, so that it can really be digested.

We can compare Promise to a nanny, a series of things at home, you just need to tell him, he can help you do it, you can do other things.
For example, as the head of the family, I have to go out to work one day, but I still have to buy food and cook and send it to my wife's unit (please understand my status at home ...)

Things to do when going out are important, as is buying food and cooking. But I can only do one thing myself.

At this time, I can give the nanny the job of buying food and cooking. I will tell her:

  • You go to the supermarket to buy food first.
  • Cook with the dishes bought in the supermarket.
  • Send the prepared meals to the wife's unit.
  • Call me when you get to the unit.

We know that the above three steps are time-consuming, and we can understand them as three asynchronous tasks. Use Promise to write this operation:

function grocery shopping (resolve, reject) { 
    setTimeout ( function () { 
        resolve ([ 'tomato', 'egg', 'oilseed' ]); 
    }, 3000 ) 
} 
function cooking (resolve, reject) { 
    setTimeout ( function ( ) {
         // The next step is to process the cooked rice. 
        Resolve ({ 
            Main food: 'rice' , 
            dishes: [ 'tomato scrambled eggs', 'clear fried rape' ] 
        }) 
    }, 3000 )) 
} 
function to send rice (resolve , Reject) {
     // 
    Resolve ('My wife's da da' ) for the result of the meal delivery 
} ; }
function call me () {
     // The next step after call me, 
    add 100 yuan bonus to the nanny; 
}

Ok, now I have sorted out four tasks. At this time, I need to tell the babysitter and let him follow the task list.

This process is essential because if you do n’t tell the babysitter, the babysitter does n’t know what needs to be done. . (My babysitter is lazy)

// Tell the babysitter to help me do a few coherent things, first go to the supermarket to buy food 
new Promise ( buying food)
 // use the food you buy to 
cook.then ((buying food) => {
     return  new Promise (cooking) ; 
}) 
// Send the prepared meal to the wife 
company.then ((prepared meal) => {
     return  new Promise (send meal); 
}) 
// Call and notify me after the 
meal.then (( Meal delivery results) => { 
    Call me (); 
})

At this point, I informed the babysitter to do these things, and then I can safely do my things.

Please keep in mind that if our follow-up task is an asynchronous task, we must return a new promise object.
If the follow-up task is a synchronous task, you only need to return a result.
The example we gave above, except that the phone informs me that it is a synchronous task, the rest are asynchronous tasks, the asynchronous task return is the promise object.

In addition, it must be remembered that a Promise object has three states, and once the state changes, it cannot be changed to other states.

  • pending, the asynchronous task is in progress.
  • resolved (also called fulfilled), the asynchronous task is successfully executed.
  • rejected, asynchronous task execution failed.

Promise usage summary

Promise has so many concepts that it is difficult for beginners to digest it all at once, so we can adopt the forced memory method to force ourselves to remember the use process.

First initialize a Promise object, which can be created in two ways, both of which will return a Promise object.

  • 1、new Promise(fn)
  • 2、Promise.resolve(fn)

Then call the then method of the promise object returned in the previous step to register the callback function.

  • The callback function in then can have one parameter or no parameters. If the callback function in then depends on the return result of the previous step, then bring the parameters. such as
    new Promise(fn)
    .then(fn1(value){
        //处理value
    })
  • Finally, register the catch exception handling function to handle the exceptions that may be thrown in the previous callback.

Usually follow these three steps, you can deal with most asynchronous processing scenarios. After you are familiar with it, you can study the deeper principles and usage of each Promise function.

After seeing this, we can answer questions 4 and 5 above.

Promsie and event loop

When the Promise is initialized, the incoming function is executed synchronously, and then the then callback is registered. After registration, continue to execute the synchronization code, before then, the callback will not be executed in then.

After the execution of the synchronous code block is completed, it will detect whether there is a promise callback available in the event loop. If so, then execute it. If not, continue to the next event loop.

About Promises There is also a concept of microtasks (microtask) in the event loop. If you are interested, you can learn more. Although it is slightly different from the browser, the execution timing of Promise microtasks is not much different.

Promise upgrade async / await

ES6 has generator and async / await syntax, which makes asynchronous processing closer to synchronous code writing and better readability. At the same time, exception catching and synchronous code writing tend to be consistent. The above example can be written like this:

(async () => ( 
    let vegetables = await to buy vegetables (); 
    let meals = await to cook (vegetables); 
    let meal delivery results = await meal delivery (meals); 
    let notification results = await notify me (meal delivery results) ; 
}) ();

Is it clearer? It should be remembered that async / await is also based on Promises, so we still need to understand Promises in depth.

Guess you like

Origin www.cnblogs.com/magicg/p/12741988.html