【高频面试题】Promise系列(实现allSettled)

390 阅读1分钟

目录

  1. 实现allSettled
  • Promise.allSettled() 可以获取数组中每个 promise 的结果,无论成功或失败

一、实现allSettled

与 Promise.all 不同的是,当 promisereject 之后,我们不会直接 reject ,而是记录下该 reject 的值和对应的状态 'rejected'

同样地,当 promise 对象被 resolve 时我们也不仅仅局限于记录值,同时也会记录状态 'fulfilled'

当所有的 promise 对象都已执行(解决或拒绝),我们统一 resolve 所有的 promise 执行结果数组

Promise.allSettled1 = function (promises) {
    return new Promise((resolve, reject) => {
      promises = Array.isArray(promises) ? promises : []
      let len = promises.length
      const argslen = len
      // 如果传入的是一个空数组,那么就直接返回一个resolved的空数组promise对象
      if (len === 0) return resolve([])
      // 将传入的参数转化为数组,赋给args变量
      let args = Array.prototype.slice.call(promises)
      // 计算当前是否所有的 promise 执行完成,执行完毕则resolve
      const compute = () => {
        if(--len === 0) { 
          resolve(args)
        }
      }
      function resolvePromise(index, value) {
        // 判断传入的是否是 promise 类型
        if(value instanceof Promise) { 
          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])
      }
    })
  }

1) 测试

const p1 = Promise.resolve(1)
const p2 = Promise.resolve(2)
const p3 = Promise.reject(0)

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

image.png

总结

  • 彼此相互依赖,一个失败全部失效(全无或全有)用 Promise.all ;相互独立,获取每个结果用 Promise.allSettled

  • Promise.allSettled() 可以获取数组中每个 promise 的结果,无论成功或失败

  • 注意: 其中任意一个 promiserejectPromise.all 就会立即被 reject ,数组中其它未执行完的 promise 依然是在执行的, Promise.all 没有采取任何措施来取消它们的执行

  • 但大多数场景中,我们期望传入的这组 promise 无论执行失败或成功,都能获取每个 promise 的执行结果,为此,ES2020 引入了 Promise.allSettled()