The introduction

This paper introduces promise.Allsettled content step by step from four aspects:

  • Promise.all()The defects of
  • The introduction ofPromise.allSettled()
  • Promise.allSettled()Promise.all()Applicable scenarios
  • handwrittenPromise.allSettled()implementation

The following text begins 👇

Promise. All the defects of ()

As we explained in a previous article, when we execute a Promise using promise.all (), we reject any Promise that fails, rejecting the first error message thrown. The success callback in.then is called only if all promises are resolved

const p1 = Promise.resolve(1)
const p2 = Promise.resolve(2)
const p3 = new Promise((resolve, reject) = > {
  setTimeout(reject, 1000.'three');
});

Promise.all([p1, p2, p3])
.then(values= > {
    console.log('resolve: ', values)
}).catch(err= > {
    console.log('reject: ', err)
})	

// reject: three
Copy the code

Note: Any one of thempromiserejectPromise.allWould have been immediatelyreject, other unfinished items in the arraypromiseIt’s still being implemented,Promise.allNo steps have been taken to cancel their implementation

In most scenarios, however, we expect the incoming set of promises to obtain the execution result of each promise regardless of failure or success. To this end, ES2020 introduces promise.Allsettled ()

Promise.allSettled()

Promise.allsettled () gets the result of each Promise in the array, whether successful or unsuccessful

const p1 = Promise.resolve(1)
const p2 = Promise.resolve(2)
const p3 = new Promise((resolve, reject) = > {
  setTimeout(reject, 1000.'three');
});

Promise.allSettled([p1, p2, p3])
.then(values= > {
    console.log(values)
})	

/* [ {status: "fulfilled", value: 1}, {status: "fulfilled", value: 2}, {status: "rejected", reason: "three"} ] */
Copy the code

When the browser does not support Promise.allSettled, you can polyfill:

if (!Promise.allSettled) {
  const rejectHandler = reason= > ({status: "rejected", reason})
  const resolveHandler = value= > ({status: "fulfilled", value})
  Promise.allSettled = promises= >
    Promise.all(
      promises.map((promise) = >
        Promise.resolve(promise) 
          .then(resolveHandler, rejectHandler)
      )
      // Each promise needs to be wrapped in promise.resolve
      // In case of passing a non-promise
    );
}

/ / use
const p1 = Promise.resolve(1)
const p2 = Promise.resolve(2)
const p3 = new Promise((resolve, reject) = > {
  setTimeout(reject, 1000.'three');
})
const promises = [p1, p2, p3]
Promise.allSettled(promises).then(console.log)
Copy the code

Promise.allsettled () and promise.all () will be settled on the same day

Promise.allSettled()More suitable for:

  • They’re not dependent on each other, and neither of them isrejectHas no effect on anything else
  • Expect to know everypromiseExecution result of

Promise.all()More suitable for:

  • Each of them is dependent on the otherrejectEverything else has lost its real value

Handwriting promise.allsettled source code

Unlike promise. all, when a Promise is rejected, we don’t reject it directly. Instead, we record the reject value and the state ‘rejected’;

Similarly, when a promise object is resolved we are not limited to recording the value, but also recording the state ‘fulfilled’.

When all promise objects have been executed (resolved or rejected), we resolve all promise execution results

MyPromise.allSettled = function (promises) {
    return new MyPromise((resolve, reject) = > {
      promises = Array.isArray(promises) ? promises : []
      let len = promises.length
      const argslen = len
      // If an empty array is passed, return a resolved empty array Promise object
      if (len === 0) return resolve([])
      // Convert the passed arguments to an array and assign them to the args variable
      let args = Array.prototype.slice.call(promises)
      // Determine whether all promises have been executed. Resolve when all promises have been executed
      const compute = () = > {
        if(--len === 0) { 
          resolve(args)
        }
      }
      function resolvePromise(index, value) {
        // Check whether a promise type was passed in
        if(value instanceof MyPromise) { 
          const then = value.then
          then.call(value, function(val) {
            args[index] = { status: 'fulfilled'.value: val}
            compute()
          }, function(e) {
            args[index] = { status: 'rejected'.reason: e }
            compute()
          })
        } else {
          args[index] = { status: 'fulfilled'.value: value}
          compute()
        }
      }
   
      for(let i = 0; i < argslen; i++){
        resolvePromise(i, args[i])
      }
    })
  }
Copy the code

conclusion

One failure is all or nothing. Independent of each other, obtain each outcome using promise.allsettled

Three minutes a day, advance one