Promise is another asynchronous programming solution that is more reasonable and powerful than the callbacks + events approach we introduced earlier.

Promise’s task queue and priority

The callback event described in the previous article is to submit an asynchronous task to a human task queue for polling by the main thread

Promise also commits an asynchronous task to a task queue, but not a normal asynchronous task queue, but a microtask queue.

As opposed to a normal asynchronous event task queue which is a macro task queue,

So the same task list main thread polls the microtask list in a limited way

A microtask queue is a higher priority than a macro task queue

SetTimeout (()=>{console.log(' macro task list event)}) // Promise - new Promise((resolved, Reject) => {console.log('Promise') resolved(' microtask list event ')}). Then (value => {console.log(value)}) // Synchronize task Console. log(' sync event ')Copy the code

Therefore, the priority of asynchronous programming is divided into: synchronous task = synchronous task < micro task < macro task defined by Promise

The same synchronization tasks are performed in sequence

The macro task in Promise increases

It’s just a matter of knowing that within the Promise definition block is synchronized code, so when in the sync block

When a setTimeout() event is defined and the Promise state change is wrapped, the macro task executes before the microtask

Because the microtask has not yet been invoked in the list of microtasks

New Promise(resolved =>{setTimeout((=>{console.log(' asynchronous task ') resolved('Promise task ')})}). console.log(value) })Copy the code

Here the Promise task is executed only after the asynchronous task completes.

The basic syntax for promises

Here are two ways to write a Promise – a base definition and a wrapper definition

New Promise((resolve,reject) =>{resolve() reject()}).then(res=>{// successful callback}).catch(err=>{// failed callback}) // Encapsulate the definition function Promise(){ return new Promise((resolve,reject) => { resolve() reject() } })}Copy the code

The three states and singleness of the states of Promise

A Promise is simply a container that contains the result of an event that will happen or end in the future,

Promise is again an object that has three states

  • Wait (pedding)
  • Success (resolved)
  • Failure state (Reject)

When there is no trigger, the state of the Promise is waiting. Once the trigger is triggered, the successful or failed state cannot be cancelled again, and the state is unique

** can ignore one of two states in a Promise,** responds to only one state, and then can be written forever

new Promise((resolve, reject)=>{
    resolve()
    reject()})
.then(null,res=>{

})
.then(null,res1=>{

})
Copy the code

Then is also a Promise

Then is a Promise, and the first THEN determines which one to execute based on whether the return succeeds or fails

The second THEN defaults to success, or the second THEN, if there is no Promise, is a chained function, with no Promise state response

A Promise corresponds to a then

Then (res=>{return '111'},null). Then (res1=>{sole.log(res1) // 111}) // Then new Promise(()=>{resolved()}). Then (res=>{return new Promise((resolved,reject)=>{reject(' error message ')})}) Then (null, (err) = > {the console. The log (err) / / error message})Copy the code

Error handling in promises

When a Promise state is REJECT, the second function of then is the callback that accepts the error message

New Promise((resolved, reject) =>{reject(' error ')}). Then (null,(err)=>{console.log(err) // Error})Copy the code

Another case where you don’t need to deal with specific THEN errors is when you can use a catch for unified processing, which means you can use a catch for multiple promises

New Promise((resolved, reject) => {reject(' error ')}). Then (res => {// normal processing status}). Catch (err => {// If no error callback is written Execute the uniform error callback function})Copy the code

So there are actually two states of error handling for a Promise, one is that the specific error handling is executed using the second argument to then, and once it’s executed it doesn’t go anywhere near the catch, right

The second is an error callback with no THEN, in which all error messages are summarized to catch execution

The use of the finally

Finally is a function that executes after a function executed with a success or failure callback. That is, when the Promise state changes from success to failure,finally will execute after them, no matter what the state is

New Promise ((resolve, reject) = > {reject (' failure ')}), then (res = > {}). The catch (err = > {}). The finally (() = > {})Copy the code

This can be done with loading state execution, which is invoked when a Promise asynchro is initiated and turned off when a Promise asynchro succeeds or the callback completes

Resolve to use

Resolve is an abbreviated form of the successful state of a Promise, which can return a successful state directly

Function query(){return promise.resolve (' successful state ')} Reject) => {resolve(' successful state ')})}Copy the code

Resolve is much more convenient than writing a full Promise

The use of reject

Like resolve,reject can return an error state directly, either as a callback in a specific function of THEN or as a catch

new Promise((resolve,reject) => {

})
.then(res => {

])
.catch(err => {
    
})
Copy the code

Promise. The use of all

The Promise.all interface can be used when multiple interfaces need to request together and obtain requirements for request data simultaneously

For example, if you have a requirement that you click on the TAB Food and attractions and we need to send the food and attractions data request together, use promise.all to accept it

Promise.all has two features

1. Successful callback is executed only when all all requests are successful

2. An error callback is executed when one of all Promise asynchronous operations fails

Promise. All ([request 1, 2]). Then (res = > {}). The catch (err = > {})Copy the code

We currently have this requirement: click the label button of food and scenic spot to synchronously obtain the data of these two requests, promise.all

Let tagArr = [' gourmet ',' tourist '] functon getTagdata(names){let Promise = names.map(val => {return ajax(' ${baseUrl}${value} ') }) return Promise(Promise) } getTagdata(tagArr) .then(res => { console.log(res) }) .catch(err => { console.log(err) }) .finally(()=>{// do some work after the data request})Copy the code

The use of Promise. AllSettled

Promise.allsettled and promise.all are similarly defined, except that promise.all will not execute a successful callback if one of the requests is settled in error

The Promise. AllSettled will be executed successfully even if there is a mistake. Only the array will be returned with “fulfilled” or “Rejected” status.

Promise.allsettled (promis).then(res => {// perform the operation})Copy the code

For example, if we request several requests and one request is in error, we still display the correct request and filter the incorrect request

Promise.allSettled(promis)
.then(res => {
    res.filter(value => {
        let successArray = value.status === 'fulfilled'
    })
})
Copy the code

Promise. The use of the race

The syntax of promise. race is similar to that of promise. all, which is also multiple asynchronous operations, except that no matter how many asynchronous operations there are, promise. race returns only one result, which is a faster response to the request

Promise. Race ([' request event 1 ', '2' request events]), then (res = > {/ / success callback}). The catch (err = > callback} {/ / failure). The finally (() = > { Console. log(' promise.race completed ')})Copy the code

I usually use promise.race as the cut-off time for web requests

Function timeOut(delay){return new Promise((resolve, reject) => {setTimeout(() => {reject()) => {reject()) ')}, delay)})} Promise. Race ([ajax (' network request address), the timeOut (1000)]), then (res = > {the console. The log (res)}). The catch (err = > { The console. The log (err)}). The finally (() = > {the console. The log (' complete ')})Copy the code

The code race has two asynchronous operations, a network request and a timer. The timer is executed at a scheduled time

If the network request is not completed within the specified time, the timer task is executed to return that the network request has timed out.

Promise task queue

A Promise’s task queue is essentially the order in which Promise events are executed

General order of Promise execution

We can clearly know the execution order of a Promise by remembering one principle, that is, a Promise corresponds to a THEN and only after the first THEN is executed can the next Promise be executed

The new Promise ((resolve, reject) = > {} / / synchronization code), then (() = > {return Promise. The resolve ()}), then (() = > {/ / / execution})Copy the code

A chain of Promise tasks is generated

Use a map to encapsulate the Promise event execution order

The core idea encapsulated with a map is that there must be an advance Promise to execute, and a THEN is returned to execute subsequent results

For example, if you have two Promise events, use the event loop to make the Promise event chain

function qunue(num){
    let promise = Promise.resolve()
    num.map(v=> {
        promise = promise.then(_ => {
            return v()
        })  
    })
}

funciotn fun1(){
    return new Promise((resolve, reject) => {
        setTimeout(_ => {
            console.log('fun1')
        },2000)
    })
}
function fun2(){
    return new Promise((resolve, reject) => {
       setTimeout(_ => {
            console.log('fun2')
        },1000)     
    })
}

qunue([fun1,fun2])
Copy the code