JavaScript中结合async/await与Promise,优化循环调用resolveName的代码
问题修复指南:让
resolveName在循环中正常执行 我帮你梳理下代码里的几个关键问题,然后一步步修复,确保resolveName能在循环中正确返回解析后的公司名称:
1. 先解决resolveName的核心问题
当前你的resolveName函数有两个致命问题:
- 没有返回数据库查询的Promise,导致
await resolveName()根本拿不到结果 - 函数里直接使用
res对象报错(这个函数没接收req/res参数),错误处理应该交给上层的接口函数
修正后的resolveName改成async函数,直接返回Promise结果:
async function resolveName(c_id) { try { // 用await替代.then,代码更清晰 const company = await localDB.find({ selector: { type: 'company', _id: c_id }, fields: ['companyName'], }); // 存在数据就返回名称,否则返回null return company.docs.length >= 1 ? company.docs[0].companyName : null; } catch (err) { console.log('解析公司名称出错:', err); // 把错误抛给上层处理,不要在这个函数里操作res throw err; } }
2. 修复循环变量的全局污染问题
你的for循环里的i和j没加let/const声明,会变成全局变量,导致循环逻辑混乱,必须加上声明。
3. 重构getAllItems函数,统一用async/await
原来的函数混合了.then()和async/await,代码可读性差,我们统一用async/await,同时处理所有错误:
基础修复版(串行请求)
const getAllItems = async function(req, res) { try { // 先获取所有item数据 const result = await localDB.find({ selector: { type: 'item' }, fields: ['_id', 'itemNumber', 'itemName', 'compatablities', 'companyID'], sort: ['_id'] }); if (!result) { return res.status(200).json({ refinedResult: [] }); } const refinedResult = []; // 用let声明循环变量i for (let i = 0; i < result.docs.length; i++) { const doc = result.docs[i]; // 解析当前item的公司名称 const companyName = await resolveName(doc.companyID); const parentItem = { itemName: doc.itemName, itemNumber: doc.itemNumber, companyID: doc.companyID, parentItemNo: "Parent", companyName // 把解析后的名称加进去 }; refinedResult.push(parentItem); // 处理兼容性项,先判断compatablities是否存在,避免报错 const compatList = doc.compatablities || []; // 用let声明j for (let j = 0; j < compatList.length; j++) { const compat = compatList[j]; // 解析兼容性项的公司名称 const compatCompanyName = await resolveName(compat.companyID); const compatItem = { itemName: doc.itemName, itemNumber: compat.itemNumber, companyID: compat.companyID, parentItemNo: doc.itemNumber, companyName: compatCompanyName }; refinedResult.push(compatItem); } } return res.status(200).json({ refinedResult }); } catch (err) { console.log('获取物品列表出错:', err); return res.status(500).json({ error: err.message }); } };
性能优化版(并行请求)
上面的代码是串行调用resolveName,如果数据量大,接口会很慢。我们可以先收集所有需要解析的公司ID,一次性并行查询,大幅提升速度:
const getAllItems = async function(req, res) { try { const result = await localDB.find({ selector: { type: 'item' }, fields: ['_id', 'itemNumber', 'itemName', 'compatablities', 'companyID'], sort: ['_id'] }); if (!result) { return res.status(200).json({ refinedResult: [] }); } // 收集所有需要解析的公司ID,用Set去重 const allCompanyIds = new Set(); result.docs.forEach(doc => { allCompanyIds.add(doc.companyID); (doc.compatablities || []).forEach(compat => { allCompanyIds.add(compat.companyID); }); }); // 并行查询所有公司名称,构建ID到名称的映射表 const companyNameMap = {}; await Promise.all(Array.from(allCompanyIds).map(async (id) => { const name = await resolveName(id); companyNameMap[id] = name; })); const refinedResult = []; for (let i = 0; i < result.docs.length; i++) { const doc = result.docs[i]; const parentItem = { itemName: doc.itemName, itemNumber: doc.itemNumber, companyID: doc.companyID, parentItemNo: "Parent", companyName: companyNameMap[doc.companyID] }; refinedResult.push(parentItem); const compatList = doc.compatablities || []; for (let j = 0; j < compatList.length; j++) { const compat = compatList[j]; const compatItem = { itemName: doc.itemName, itemNumber: compat.itemNumber, companyID: compat.companyID, parentItemNo: doc.itemNumber, companyName: companyNameMap[compat.companyID] }; refinedResult.push(compatItem); } } return res.status(200).json({ refinedResult }); } catch (err) { console.log('获取物品列表出错:', err); return res.status(500).json({ error: err.message }); } };
这样修改后,你的代码就能正常工作,而且性能也更好啦。
内容的提问来源于stack exchange,提问作者Mike T
相关产品推荐
相关产品推荐

