A Promise is an object that represents the completion or failure of an asynchronous operation. Here’s what the MDN says about promises. In front-end development, promises are often used to deal with asynchrony and callbacks to avoid callback hell and better lay out asynchrony related code. This article will document some of my own understanding and experience of promises and related async/await.

I. Three states of Promise

A Promise is a Promise, and the outcome of that Promise will be either success or failure. Moreover, we don’t get immediate results when we make a promise, and we need a little more time to fulfill the promise before we get a successful or unsuccessful result. Promises are structured a lot like promises in our lives.

The diagram above is the Promise structure. Just like the Promise in our life, there are three states in a Promise: the pending state of fulfilling the Promise, the Rejected state when the Promise fails, and the Fullfilled state when the Promise succeeds.

Now, in the name of love, let’s make a promise:


let love = new Promise((resolve, reject) => {
    setTimeout(() => {// Start a love affair, but the result of love will be known laterletHappy = math.random () >= 0.3?true : false
        if ( happy ) {
            resolve('marry'// Success in love, decide to get married}else {
            reject('break') / / love failure, decided to break up}}, 500)}) love. Then (result = > {the console. The log (result) / / processing love success callback, the result is above and resolve'marry'}). Catch (result => {console.log(result), reject (reject), reject (reject'break'
})

Copy the code

The code above is an example of a simple but complete Promise. It should be noted that a Promise will be solidified when it reaches the success or failure state through pending state, that is, it will never fail again after reaching the success state, and it will never return to the success state after failure.

So the following Promise must be a failed state, even if it is followed by reject and resolve. Is the so-called: if love, please deep love, if abandoned, please completely, not ambiguous, wounding hurt yourself. Plato is talking about the solidification of the Promise.

let love = new Promise((resolve, reject) => {
    reject('break')
    resolve('marry')
})

love.then(result => {
    console.log(result)
}).catch(result => {
    console.log(result)
})
Copy the code

I Promise to make a Promise then and catch it

The first, and most common, is to use then to catch resolve and catch to catch reject

love.then(result => {
    console.log(result)
}).catch(result => {
    console.log(result)
})

Copy the code

Second, instead of writing catch, we write a reject function to THEN, but the effect is the same

love.then(result => {
    console.log(result)
}, result => {
    console.log(result)
})
Copy the code

And the third way, write it separately, is also fine

Then (result => {console.log(result)}) love. Catch (result => {console.log(result)})Copy the code

3. Quickly build a Promise of success or failure

Promises come with two approaches that you can use to quickly build a Promise: promise.resolve (), a Promise to build a successful state; The other is promise.reject (), which is used to build promises for failed states.


let p1 = Promise.resolve('success'Console. log(p1) // Make a Promise {'success'} p1.then(result => {console.log(result) //'success'
})

let p2 = Promise.reject('failed'P2. catch(result => {console.log(result)})Copy the code

Four, the use ofPromise.all()To handle a class of front-end scenarios

In front-end development practice, we sometimes encounter the need to send multiple requests and return data according to the request order. For example, we want to send a, B, and C requests. The three requests return data as A1, A2, and A3, respectively, and we want A1, A2, and A3 to return data in the order we want. The promise.all () method is a perfect solution to this problem.

Assume the following code is used:

// A function that simulates asynchronous requestslet request = (name, time) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            let random = Math.random()
            if(random >= 0.2) {resolve('${name}Success ')}else {
                reject(`${name}Failed to ')}}, time)})} // Build three Promise instanceslet a = request('Ming', 1000).let b = request('little red', 500).let c = request('xiaohua'// use promise.all (), Promise.all([b,a,c]).then(result => {console.log(result)}).catch(result => {console.log(result)})Copy the code

What happens if you copy the code above and run it a few more times in the browser’s debug console (refresh the second time)? As you might guess, if all three requests are successful, the data returned from all three requests is in the order in which they were sent, i.e., ‘Xiao Hong succeeded ‘,’ Xiao Ming succeeded ‘, and ‘Xiao Hua succeeded ‘, and is returned as an array. When one of the requests fails, only the result of the first failure is returned.

Of course, the promise.all () method can be used in other places besides this scenario. For example, if there are two requests on a page, the page will be displayed only when the data of the two requests is received. Before this, a loading diagram will be displayed. Promise.all() is also a neat way to solve this problem.

Five, the chain call of Promise

The then method mentioned above continues to return a Promise object after each use.

let p = Promise.resolve('success')
letResponse = p.teng (result => {console.log(result)}) console.log(response) // The typed response is a Promise objectCopy the code

Since the return from then is still a Promise object, we can continue with “then”, except that the “then” takes the same argument as the return from the previous “THEN”, The content of this return can be either a plain string, number, etc. (which will eventually be wrapped as a Promise), or it can be a self-written Promise object.

Let’s follow up on the promise of love with an example of a chain call:

let love = new Promise((resolve, reject) => {
    setTimeout(() => {
        letHappy = math.random () >= 0.3?true : false
        if ( happy ) {
            resolve('marry')}else {
            reject('break')}}, 500)})let haveChild = new Promise((resolve, reject) => {
    setTimeout(() => {
       resolve('The baby is born! ') 
    }, 1000)
})


love.then(result => {
    console.log(result)
    returnHaveChild // Returns a Promise object whose resolve will be resolved by the nextthen}). Then (result => {console.log(result)return 'In the end, they grow old together! '// The string returned here is passed to the next onethen
}).then(result => {
    console.log(result)
}).catch(error => { 
    console.log(error)
})

Copy the code

It is important to add a catch at the end of a chain call to catch possible errors in the chain.

A business scenario that the Promise chain invocation can handle

Promise’s chain operation comes in handy when we need to send multiple requests, each of which always depends on the result of the previous one.

We demonstrate this using AXIos, which itself uses the Promise wrapper as follows:


let request = (url) => {
    letResult = axios.get(url) //result is a Promise object result.then(response => {return response
    }).catch(error => {
        throw new Error('Wrong! ')
    })
}

request(url0).then(response => {
    return request(response.data.link)
}).then(result => {
    console.log(result)
}).catch(error => {
    console.log(error)
})

Copy the code

The code above briefly simulates this process, with some imperfections.

The above is my understanding of the use of Promise, many places are not perfect, if wrong, also please friends can correct in time!

This is my first article on the Nuggets! Thanks for watching!