• Promise.all和Promise.allSettled的区别
  • 发布于 2个月前
  • 97 热度
    0 评论
一、前言
不管你是否还学的动,JS语言依然在以自己的节奏飞快的进化。Promise中的any()、race()、all()方法都是比较常见的;转眼间,Promise 的工具包里又多了一个方法Promise.allSettled 供你选择,它看起来像是对 Promise.all 的一种补充,缓解了使用 Promise.all 碰到reject 的痛点问题。

下面我们先来分别看下这四个方法及其区别:

二、Promise.any
Promise.any() 方法将一组可迭代的 Promises 作为输入,并返回一个 Promise,只要参数实例有一个变成 fulfilled 状态,包装实例就会变成 fulfilled 状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。
const promises = [
  Promise.reject('ERROR A'),
  Promise.reject('ERROR B'),
  Promise.resolve('result'),
]

Promise.any(promises).then((value) => {
  console.log('value: ', value)   // value:  result
}).catch((err) => {
  console.log('err: ', err)  
})
如果所有传入的 promises 都失败:
    const promises2 = [
      Promise.reject('ERROR A'),
      Promise.reject('ERROR B'),
      Promise.reject('ERROR C'),
    ]

    Promise.any(promises2).then((value) => {
      console.log('value:', value)
    }).catch((err) => {
      console.log('err:', err)
      console.log(err.errors)
    })
三、Promise.race
Promise.race()方法将一组可迭代的 Promises 作为输入,并返回一个 Promise ,顾名思义,race 就是赛跑的意思,Promise.race([p1, p2, p3]) 里面哪个结果获得的快,就返回那个结果。
const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, 'one')
})
const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'two')
})
Promise.race([promise1, promise2]).then((value) => {
  console.log(value)  // 'two'
})
四、Promise.all
Promise.all()方法将一组可迭代的 Promises 作为输入,并返回一个 Promise ,该 Promise resolve 的结果为刚才那组输入 promises 的返回结果。
const promise1 = Promise.resolve(3)
const promise2 = 42
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo')
})

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values)  //  [3, 42, "foo"]
})
当三个 promise 都完成时,Promise.all 就完成了,并且输出被打印了。如果其中一个 promise 失败了,则 Promise.all 整体将会失败。
const promise1 = Promise.resolve(3)
const promise2 = Promise.reject('error')
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo')
})

Promise.all([promise1, promise2, promise3])
    .then(values => ...)
    .catch(err => console.log(err))   // 'error'
当需要处理多个 Promise 并行时,大多数情况下 Promise.all 用起来是非常顺手的,但是一旦有一个promise 出现了异常(reject),情况就会变的麻烦。尽管能用 catch 捕获其中的异常,但你会发现其他执行成功的 Promise 的消息都丢失了,仿佛石沉大海一般。

要么全部成功,要么全部重来,这是 Promise.all 本身的强硬逻辑,也是痛点的来源,这给 Promise.allSettled 留下了立足的空间。

问题:Promise.all 如果有报错,是在 then 还是 catch 接收数据?
let p1 = Promise.resolve(1)
let p2 = Promise.resolve(2)
let p3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, "3")
});

let p4 = Promise.reject(4)
let p5 = Promise.reject(5).catch((e) => e)

// 情况1:promise全部resolve
Promise.all([p1, p2, p3]).then(values => {
    console.log(values)  // 其中p1、p2、p3都成功,所以进入then()
}).catch(function(err) {
    console.log(err)    // 永远走不到这里
});

// 情况2:promise有一个reject,且reject没有主动捕获异常
Promise.all([p1, p2, p4]).then(values => {
    console.log(values)  // 其中p4失败,且没有主动捕获异常,永远走不到这里
}).catch(function(err) {
    console.log(err)     // 此时走到catch  4
});

// 情况3:promise有一个reject,且reject主动捕获异常
Promise.all([p1, p2, p5]).then(values => {
    console.log(values)    // 其中p5失败,但是主动捕获了p5的异常,所以进入then()
}).catch(function(err) {
    console.log(err)      // 永远走不到这里
});

// 情况4:使用Promise.allSettled
Promise.allSettled([p1, p2, p4]).then(values => {
    console.log(values)   // 其中p4失败,但是使用Promise.allSettled,所以进入then()
}).catch(function(err) {
    console.log(err)
})
五、Promise.allSettled
从 ES2020 开始,你可以使用 Promise.allSettled。当所有的 promises 都已经结束无论是完成状态或者是失败状态,它都会返回一个 promise,这个 promise 将会包含一个关于描述每个 promise 状态结果的对象数组。
const promise1 = Promise.resolve(3)
const promise2 = Promise.reject(new Error('An error'))
const promise3 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'))
const promises = [promise1, promise2, promise3]
 // 堆代码 duidaima.com
Promise.allSettled(promises).then((res) => console.log(res))
六、Promise.any vs Promise.all
Promise.all() :任意一个 promise 被 reject ,就会立即被 reject ,并且 reject 的是第一个抛出的错误信息;只有所有的 promise 都 resolve 时整体才会 resolve。

Promise.any() :任意一个 promise 被 resolve ,就会立即被 resolve ,并且 resolve 的是第一个正确结果;只有所有的 promise 都 reject 时整体才会 reject。


七、Promise.any vs Promise.race
Promise.race() :返回最先完成的 promise 的结果,无论成功还是失败;假如第一个 promise 失败了,那么就会结束。

Promise.any():不会因为某个 Promise 变成 rejected 而结束,哪怕首个 promise 是 rejected,可能还会有另一个 promise 成功。


八、Promise.all vs Promise.allSettled
一句话概括两者的最大不同:Promise.allSettled 永远不会被 reject
Promise.all 将在 Promises 数组中的其中一个 Promises 失败后立即失败。
Promise.allSettled将永远不会失败,一旦数组中的所有 Promises 被完成或失败,它就会完成。
Promise.allSettled是对 Promise.all 的一种补充,解决了当多个 promise 并行时 reject 的出现会伴随着其他 promise 数据丢失的问题。
用户评论