Node.js Express异步函数结果集无法取值 无法生成嵌套JSON结构
问题原因
- 被
async修饰的getAlternativeProducts函数默认返回Promise对象,调用时没有添加await关键字等待异步操作完成,所以拿到的是处于pending状态的Promise实例,而非执行完成后的替代商品结果集。 - 接口响应流程没有等待所有替代商品的异步查询操作完成,就提前执行了
res.json(structured)返回数据,此时替代商品的查询还在执行中,返回的结果自然没有对应数据。 - 额外问题:使用全局变量
structured存储结果会存在并发请求冲突问题,多个用户同时调用接口时,全局变量会被互相覆盖,导致返回结果错乱。另外你给出的预期JSON结构中alternateproducts外层的{}属于语法错误,正确结构应该直接是数组类型。
修复代码
// 移除全局structured变量 app.route('/products') // GET endpoint .get(cors(), async function(req, res) { try { const request = new appmodule.sql.Request(); // 异步查询所有主商品 const recordset = await request.query('SELECT * FROM Products'); // 等待嵌套结构组装完成 const structuredResult = await GenerateStructuredJSON(recordset); res.json(structuredResult); } catch (err) { console.error(err); res.status(500).json({msg: '数据查询失败'}); } }); async function GenerateStructuredJSON(recordset) { const products = recordset.recordset; return await getNestedProducts(products); } async function getNestedProducts(prod) { for(let i = 0; i < prod.length; ++i) { const productId = prod[i].Id; // 添加await等待替代商品查询完成 const alternativeproducts = await getAlternativeProducts(productId); // 仅当存在替代商品时添加对应字段 if(Array.isArray(alternativeproducts) && alternativeproducts.length > 0) { prod[i].alternateproducts = alternativeproducts; } } return prod; } async function getAlternativeProducts(prodID) { const request = new appmodule.sql.Request(); request.input('prodid', appmodule.sql.Int , prodID); const queryRes = await request.query( 'SELECT Products.* FROM Products ' + 'RIGHT JOIN ProductAlternatives ON ProductAlternatives.AlternativeProductId=Products.Id ' + 'WHERE ProductAlternatives.ProductId=@prodid' ); return queryRes.recordset; }
性能优化建议
当前实现存在N+1查询问题:每有一个主商品就会发起一次数据库查询请求,当商品数量较多时性能会很差。建议将两次查询合并为一次联表查询,一次性拿到所有主商品和对应替代商品数据,再在内存中组装成需要的嵌套结构,大幅减少数据库交互次数。
内容的提问来源于stack exchange,提问作者Mobygo
相关产品推荐
相关产品推荐

