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

如何高效处理Promise数组:校验咖啡存在及属性并抛出异常

问题描述

现有如下方法:

async findOne(id: string) {
  const coffee = await this.coffeeModel.findById(id);
  if (!coffee) throw new NotFoundException('coffee not found');
  return coffee;
}

需要检查一组咖啡是否全部存在,于是编写了以下代码:

const coffeesPromises = []
arrayOfCoffees.forEach((element) => {
  coffeesPromises.push(this.findOne(element))
})

await Promise.all(coffeesPromises) 
// 若某款咖啡不存在,API会返回
{
  "statusCode": 404,
  "message": "coffee not found",
  "error": "Not Found"
}

但当尝试等待咖啡结果并对每个咖啡设置条件(比如检查sugar字段)时,如果某款咖啡不存在,错误只会在控制台抛出,不会以JSON格式返回。

曾尝试这样解决:

Promise.all(promises).then((results) =>
  results.forEach((result) => { if (!result.sugar) throw new BadRequestException('coffee has no sugar') })
);

目前采用的方式性能较慢,希望优化:

for (const coffee of arrayOfCoffees) {
  const coffeeDocuments = await this.findOne(coffee);
  if (!coffeeDocuments.sugar)
    throw new BadRequestException(
      `coffee has no sugar`,
    );
}

请问最优的处理方式是什么?


最优处理方案

核心思路

兼顾并行查询的性能(避免串行等待),同时统一处理两种异常场景(咖啡不存在、咖啡无sugar),确保所有错误都能以标准JSON格式返回。

具体实现

方案1:单查询内整合校验逻辑

把咖啡存在性检查和sugar校验合并到一个方法里,再并行执行所有查询:

// 封装带校验的查询方法
async findOneAndValidateSugar(id: string) {
  const coffee = await this.coffeeModel.findById(id);
  if (!coffee) {
    throw new NotFoundException('coffee not found');
  }
  if (!coffee.sugar) {
    throw new BadRequestException('coffee has no sugar');
  }
  return coffee;
}

// 批量校验方法
async checkAllCoffees(arrayOfCoffees: string[]) {
  try {
    // 并行执行所有带校验的查询
    await Promise.all(arrayOfCoffees.map(id => this.findOneAndValidateSugar(id)));
  } catch (error) {
    // 直接抛出异常,由框架自动转为JSON响应
    throw error;
  }
}

方案2:先批量查询再统一校验

如果需要保留原findOne方法的独立性,可以先并行获取所有咖啡,再统一校验sugar字段:

async checkAllCoffees(arrayOfCoffees: string[]) {
  try {
    // 并行查询所有咖啡
    const coffees = await Promise.all(arrayOfCoffees.map(id => this.findOne(id)));
    
    // 统一检查sugar字段
    const invalidCoffee = coffees.find(coffee => !coffee.sugar);
    if (invalidCoffee) {
      throw new BadRequestException('coffee has no sugar');
    }
    
    return coffees;
  } catch (error) {
    throw error; // 交给框架处理异常响应
  }
}

方案优势

  • 性能高效:用Promise.all并行执行数据库查询,避免了串行for-await的等待时间,效率和纯查询版的Promise.all一致。
  • 错误统一处理:通过try/catch捕获所有异常(包括404和400),确保所有错误都能被框架转为标准JSON响应,不会出现控制台抛错的情况。
  • 逻辑清晰:要么在单个查询中完成校验,要么批量查询后统一校验,代码简洁易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 07:55:31