There is a problem

1. Nesting problem

Before promises, we used to use callback functions to represent asynchrony. Callbacks are a continuation of our program. Callbacks are the simplest way to implement asynchrony in javascript, waiting for synchronous code to finish executing and then executing callback functions within a certain period of time. If the callback requires the result of the previous callback, it will be nested, such as:

request(url1,{},function(val1){
    request(url2, {data: val1}, function(val2){
        request(url3, {data: val2}, function(val3){
        
        }
    }
})
Copy the code

A lot of nesting creates what we often call a callback region. The callback region has the following problems:

  • Execution sequences are hard to track and extremely difficult to maintain
  • Code is fragile, can move one place, move everywhere
  • Abnormal program execution is abnormal and the result is unpredictable

Trust issues

Trust is the main reason of the problem of the callback function control taught a third party, this is called inversion of control, we do not know in the end when a third-party library will perform the callback function, so we can do all kinds of judgment in the callback function, such as premature as the callback, late callback, and so on, and in each such callback function every time we do repeat work. The general situation is as follows:

  • Calling the callback too early
  • Calling the callback too late
  • Call the callback multiple times
  • I don’t know whether to call back

So Promise was there to solve those problems

How to solve the problems mentioned above

1. Nesting problem

A Promise prototype defines a then method that returns a new Promise, creating a chained invocation that determines the order of the invocation, as in the following:

function ajax(url, data){
    return new Promise((resolve, reject)=>{
        request(url, data, function(res){
            resolve(res)
        })
    })
}

ajax()
 .then((res1)=> ajax(url1, res1))
 .then((res2)=> ajax(url2, res2))
 .then((res3)=> ajax(url3, res3))

Copy the code

Code readability is improved and order can be easily tracked

Trust issues

  1. Prematurely called.

The callback function of Promise’s then method is always asynchronous and exists on the microtask queue, so there is no premature

  1. Too late call

After a Promise state is made, the callback function registered by the then method must be called before the next asynchronous execution, so there is no delay

  1. Multiple calls

Promises cannot be changed once the state is set, so only one callback can be performed

  1. Do not know whether to call

As long as the then callback is registered, it must be called

Promise specification

Promise uses the Promise/A+ specification, which is in English and Chinese

Promise prototype approach

1. then

The then method returns a new Promise that accepts up to two arguments, one for a success callback and one for a failure callback

// p.then(onFulfilled[, onRejected]); const promise1 = new Promise((resolve, reject) => { // resolve('success'); reject('error! '); }); promise1.then((value) => { console.log(value); },(reason)=>{ console.log(reason) });Copy the code

A callback to then can return a value as follows:

  • If a value is returned, then the Promise returned by then becomes the accepted state, and this value is taken as an argument to the callback function that accepts the state
const promise1 = new Promise((resolve, reject) => {
  resolve('success');
});

promise1.then((value) => {
  console.log(value);
  return 1
}).then((res)=>{
  console.log(res) // 1
})
Copy the code
  • If no value is returned, then the Promise returned by then becomes the accepted state, and the callback that accepts the state takes undefined
const promise1 = new Promise((resolve, reject) => {
  resolve('success');
});

promise1.then((value) => {
  console.log(value);
}).then((res)=>{
  console.log(res) // undefined
})
Copy the code
  • If an error is thrown, the Promise returned by then becomes the rejection state, and the error message is taken as an argument to the rejection state callback
const promise1 = new Promise((resolve, reject) => {
  resolve('success');
});

promise1.then((value) => {
  console.log(value);
  throw 'error'
}).then(null, (error)=>{
  console.log(error) 
})
Copy the code
  • If it is a Promise that accepts the state, then returns the Promise as the acceptance state and takes the value of the Promise’s acceptance state callback as the parameter value of the Promise’s acceptance state callback
const promise1 = new Promise((resolve, reject) => {
  resolve('success');
});

promise1.then((value) => {
  console.log(value);
  return Promise.resolve(22)
}).then((res)=>{
  console.log(res) // 22
})
Copy the code
  • If it is a Promise with a rejection state, then returns the Promise with the rejection state and takes the value of the Promise’s rejection state callback as the parameter value of the Promise rejection state callback
const promise1 = new Promise((resolve, reject) => {
  resolve('success');
});

promise1.then((value) => {
  console.log(value);
  return Promise.reject('error')
}).then(null, (error)=>{
  console.log(error) // error
})
Copy the code
  • If it is a Promise in a pending state, then returns the Promise in the pending state, the final state of the Promise is the same as the final state of the Promise, and the arguments to the final state of the Promise’s callback function are the arguments to the final state of the Promise’s callback function
const p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve(123) },2000) }) Promise.resolve().then(() => { return p1 }).then((res) => { Console. log(res) // 2s after 123})Copy the code

2. catch

Catch () will also return a Promise and process the rejection. The.catch() is actually just.then() with no parameter position reserved for onFulfilled. I could rewrite it like this

Promise.prototype.catch = function(onRejected){ 
  return this.then(null, onRejected)
}
Copy the code

Use catch to catch errors

var p1 = new Promise(function(resolve, reject) { resolve('Success'); }); p1.then(function(value) { console.log(value); // "Success!" throw 'oh, no! '; }).catch(function(e) { console.log(e); // "oh, no!" throw 'o' })Copy the code

3. finally

The finally() method returns a Promise. At the end of the promise, the specified callback function will be executed, whether the result is fulfilled or Rejected. This provides a way for code to be executed after a Promise is successfully completed or not. This avoids the need to write the same statement once in both then() and catch().

Var loading = true var p1 = new Promise(function(resolve, reject) {resolve('Success'); }); p1.then(function(value) { }).catch(function(e) { }).finally(function(){ loading = false })Copy the code

Promise static method

1. all

The all method accepts an iterable type. Array, Map, and Set are all ES6 iterable types), and return only one promise instance. Resolve is an Array of all iterable promise callbacks. The parameter value of the callback function to accept the state of then; Reject is executed if there is only a Reject in iterable and the reject error message is used as the value of the reject state callback for then. Resolve the situation

// 
var p1 = new Promise((resolve, reject) => {
  resolve(1)
})
var p2 = new Promise((resolve, reject) => {
  resolve(2)
})
var p3 = new Promise((resolve, reject) => {
  resolve(3)
})

Promise.all([p1, p2, p3]).then((res) => {
  console.log(res) //  [1, 2, 3]
})
Copy the code

The condition of the reject

var p1 = new Promise((resolve, reject) => {
  resolve(1)
})
var p2 = new Promise((resolve, reject) => {
  reject('error 2')
})
var p3 = new Promise((resolve, reject) => {
  resolve(3)
})

Promise.all([p1, p2, p3]).then((res) => {
  console.log(res) 
}, (error) => {
  console.log(error) // error 2
})
Copy the code

2. allSettled

The allSettled() method returns a promise that all given promises have resolved or rejected, and returns an array of objects that are the result of the promise

var p1 = new Promise((resolve, reject) => {
  resolve(1)
})
var p2 = new Promise((resolve, reject) => {
  reject('error 2')
})

Promise.allSettled([p1, p2]).then((res) => {
  res.forEach(item => {
    console.log(item)
  })
})

//{status: "fulfilled", value: 1}
//{status: "rejected", reason: "error 2"}
Copy the code

3. any

This method is used to return the first successful promise. This method terminates as soon as one promise succeeds, rather than waiting for all the other promises to complete. Accept an iterable type argument and execute the onRejected callback if no promise succeeds. Resolve the situation

var p1 = new Promise((resolve, reject) => {
  resolve(1)
})
var p2 = new Promise((resolve, reject) => {
  resolve(1)
})
var p3 = new Promise((resolve, reject) => {
  reject('error 3')
})

Promise.any([p1, p2, p3]).then((res) => {
  console.log(res) // 1
})
Copy the code

The condition of the reject

var p1 = new Promise((resolve, reject) => {
  reject(1)
})
var p2 = new Promise((resolve, reject) => {
  reject('error 2')
})

Promise.any([p1, p2]).then((res) => {
  console.log(res)
},(error)=>{
  console.log(error) // AggregateError: All promises were rejected
})

Copy the code

4. race

The RACE method returns a promise. Once a promise in the iterator is accepted or rejected, the returned promise is either accepted or rejected. The method takes an iterable parameter.

var p1 = new Promise(function(resolve, reject) { setTimeout(resolve, 500, "one"); }); var p2 = new Promise(function(resolve, reject) { setTimeout(resolve, 100, "two"); }); Promise.race([p1, p2]).then(function(value) { console.log(value); // "two" // both complete, but p2 is faster});Copy the code

5. resolve

Resolve returns a resolved Promise object, which is a promise that accepts the state.

The parameters are as follows:

  • A value that is used as a callback argument to accept the state as the Promise returned by THEN
  • If the state is not passed or undefined, use undefined as a callback argument to accept the state as a promise returned by then
  • The Promise object, which returns the promise object directly
var p1 = Promise.resolve(123) var p2 = Promise.resolve() var p3 = Promise.resolve(p1) p1.then((res) => { console.log(res) }) p2.then((res) => { console.log(res) }) p3.then((res) => { console.log(res) }) // 123 // undefined //  123Copy the code

6. reject

Reject Returns a reject promise object. Promise.reject(reason) Parameter Reason Specifies the reason for the rejection

var p1 = Promise.reject(new Error('error'))

p1.then(null, (reason) => {
  console.log(reason)
})

//  Error: error
Copy the code

Promise related information is first introduced here, next we will write A MyPromise through the promise /A+ specification, and implement the above method, please look forward to