Promise 使用的两个注意点

11 阅读1分钟

all、allSettled 区别

两者的区别,就在于 all 必须是所有的 promisestatus 都是 fulfilled,才会执行后续代码,否则就会执行 catch 中的代码。而 allSettled 只要所有的 promisestatus 不是 pending 就会执行后续代码。

async function getResolve(p) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve({ result: p })
    }, 1000)
  })
}
async function getReject(p) {
  return new Promise((_, reject) => {
    setTimeout(() => {
      reject({ result: p })
    }, 1000)
  })
}
// 例子1
;(async () => {
  try {
    const result = await Promise.all([getResolve(1), getResolve(2)])
    console.log("result - all: ", result)
  } catch (error) {
    console.log("error - all: ", error)
  }
})()
// 例子2
;(async () => {
  try {
    const result = await Promise.allSettled([
      getResolve(1),
      getResolve(2),
      getReject(3)
    ])
    console.log("result - allSettled: ", result)
  } catch (error) {
    console.log("error - allSettled: ", error)
  }
})()

例子1的执行结果为:

error - all:  { result: 3 }

例子2的执行结果为:

result - allSettled:  [
  { status: 'fulfilled', value: { result: 1 } },
  { status: 'fulfilled', value: { result: 2 } },
  { status: 'rejected', reason: { result: 3 } }
]

比如我们并发请求了两个接口,其中一个成功了之后就可以将信息展示,就应该使用 allSettled

简单实现

Promise.prototype.all = function (values) {
  return new Promise((resolve, reject) => {
    const result = []
    let index = 0
    function processData(key, value) {
      result[key] = value
      index += 1
      if (values.length === index) {
        resolve(result)
      }
    }

    for (let i = 0; i < values.length; i++) {
      let current = values[i]
      if (isPromise(current)) {
        current.then(value => {
          processData(i, value)
        }, reject)
      } else {
        processData(i, current)
      }
    }
  })
}

timeout 如何实现

可以使用 Promise.race 来实现。

;(async () => {
  try {
    const res = await Promise.race([getResolve(3), timeout()])
    console.log("race result: ", res)
  } catch (error) {
    console.log("race error: ", error) // 执行结果: race error:  timeout
  }
})()

简单实现

Promise.prototype.race = function (promiseArr) {
  return new Promise(function (resolve, reject) {
      for (let promise of promiseArr) {
          if (isPromise(promise)) {
              promise.then(resolve, reject);
          } else {
              resolve(promise);
          }
      }
  })
}

还有一个就是 promise.any 这个就是一定要等到一个 fulfilled 之后才会执行后面的代码。