You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Promise.all中单个Promise被拒时如何终止其余操作并回滚?

核心原理说明

Promise本身不支持取消已启动的异步任务,你调用Promise.all时传入的所有Promise实例在创建的那一刻就已经开始执行了,因此Promise.all报错终止仅会中断后续的结果接收逻辑,已经执行的操作不会自动撤销。要实现「任意任务失败,所有修改都不生效」的效果,需要根据场景选择延迟提交修改或者事务回滚的方案。

Demo代码场景解决方案

针对修改内存变量的场景,最简单的方案是延迟修改原变量,所有异步逻辑先输出临时结果,等全部Promise执行成功后再合并到原变量中,代码示例如下:

exports.myFunction = async () => {
  const array = []
  try {
    const p1 = Promise.resolve(3);
    // 异步逻辑先将结果存在临时变量,resolve返回临时结果,不要直接修改原array
    const p2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        const tempArr = [1,2,3]
        resolve(tempArr)
      }, 2000);
    });

    const p3 = new Promise((resolve, reject) => {
      setTimeout(() => {
        reject("foo");
      }, 2000);
    });
    
    const [a, tempArr, c] = await Promise.all([p1, p2, p3])
    // 全部Promise执行成功后,再修改原变量
    array.push(...tempArr)
    console.log(a, tempArr, c)
  } catch (err) {
    console.log({array}) // 此时array仍为空,符合预期
    console.log({err})
  }
}
exports.myFunction()
Mongo业务场景解决方案

你的Mongo操作场景本质是需要实现多操作的原子性,直接使用MongoDB自带的事务特性即可,无需自己实现回滚逻辑,代码示例如下:

// 开启会话
const session = await User.startSession()
// 启动事务
session.startTransaction()
try {
  const [updateRes, aggregateRes] = await Promise.all([
    // 所有操作都绑定当前事务会话
    User.updateOne(
      { _id: id }, 
      { $set: { isDone: true }},
      { session }
    ),
    Notification.aggregate([/* 你的聚合逻辑 */], { session })
  ])
  // 全部操作成功,提交事务
  await session.commitTransaction()
} catch (err) {
  // 任意操作报错,回滚事务,之前的update操作会被撤销
  await session.abortTransaction()
  console.error('操作失败,已回滚所有修改:', err)
} finally {
  // 关闭会话
  await session.endSession()
}

注意事项:MongoDB 4.0及以上版本才支持事务,且需要运行在副本集或分片集群模式下,本地单节点开发时需要配置单节点副本集才能正常使用事务。

内容的提问来源于stack exchange,提问作者Profer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 15:30:00