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

如何并行执行更新操作

关于Promise构造器使用async回调的问题分析

嘿,我看到你发现了一个有趣的现象——当把async函数作为new Promise()的回调参数时,你的数据库查询能正常执行,并且在Promise.all([]).then()里能拿到预期结果,而用普通非async回调时可能达不到预期。咱们来拆解一下这个情况:

为什么async回调能解决你的问题?

先看你给出的示例代码片段:

const borrowersFeePromise = new Promise(async (resolve, reject) => {
  if (borrowersFee !== undefined && borrowersFee !== '') {
    const borrowersFeeUpserted = await Fees.update(
      { 
        personId: mongoose.Types.ObjectId(personId), 
        category: 'borrowersFee', 
      },
      { $set: { amount: borrowersFee } }
      // 猜测你可能漏了upsert选项,不过这不影响核心逻辑
    );
    resolve(borrowersFeeUpserted);
  } else {
    resolve(null); // 这里处理空值的情况
  }
});

核心原因很简单:

  • 当你用async函数作为Promise构造器的回调时,内部的await会暂停回调函数的执行,直到Fees.update()这个异步数据库操作完成,之后才会调用resolve()把最终结果传递出去。
  • 而如果不用async,直接写普通回调的话,如果你没正确处理Fees.update()的异步性(比如忘记用.then()链式调用,或者没在异步操作的回调里调用resolve),就会导致Promise提前resolve,Promise.all拿到的是还没完成的异步操作的状态,自然得不到预期结果。

但要注意:这种写法有冗余和风险!

虽然这个写法解决了你的问题,但非常不推荐把async函数直接传给Promise构造器,原因有两个:

  • 冗余包装:async函数本身就会返回一个Promise,再套一层new Promise完全是多余的,增加了不必要的嵌套。
  • 错误处理隐患:如果await的操作抛出错误,async函数会自动把它转化为rejected状态,但因为你在Promise构造器里,这个错误可能会被构造器的reject逻辑覆盖,或者如果没加try/catch的话,会导致未捕获的异常。

更优雅的替代写法

其实你完全可以去掉外层的new Promise,直接用async函数返回Promise:

// 定义一个返回Promise的async函数
const getBorrowersFeeResult = async () => {
  if (borrowersFee !== undefined && borrowersFee !== '') {
    // 直接return await的结果,async函数会自动包装成Promise
    return await Fees.update(
      { 
        personId: mongoose.Types.ObjectId(personId), 
        category: 'borrowersFee', 
      },
      { $set: { amount: borrowersFee } },
      { upsert: true } // 加上upsert更符合常见的更新/插入场景
    );
  }
  // 空值情况直接返回null,同样会被包装成resolved的Promise
  return null;
};

// 在Promise.all里调用这个函数
Promise.all([getBorrowersFeeResult()])
  .then(results => {
    // 这里就能拿到预期的更新结果了
    console.log(results);
  })
  .catch(err => {
    // 统一捕获所有异步操作的错误
    console.error(err);
  });

这样既保持了代码的简洁性,又避免了冗余的Promise包装,同时错误处理也更清晰——如果Fees.update()出错,会直接被Promise.all的.catch()捕获,不会出现隐藏的异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:58:13