如何高效处理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
相关产品推荐
相关产品推荐

