Loopback中findById结果无法同步存入ctx.result问题求助
解决Loopback afterRemote中异步操作导致结果为空的问题
你遇到的核心问题是异步操作的执行时机:Model.findById是异步方法,它的回调函数会在未来某个时间点执行,但你的ctx.result = finalData和next()在所有异步回调完成前就已经执行了,所以此时finalData还是空数组。
解决方案:用Promise.all统一处理异步请求
Loopback的模型方法在不传入回调函数时会返回Promise,我们可以利用这个特性,结合Promise.all来等待所有异步查询完成,再将结果赋值给ctx.result。
修改后的代码如下:
let finalData = []; Model.afterRemote('find', async function(ctx, instance, next) { if (ctx.result) { if (Array.isArray(ctx.result)) { // 收集所有findById的Promise const findPromises = ctx.result.map(result => Model.findById(result.id, { include: { relation: 'users', scope: { fields: ['email'] } } }) ); // 等待所有Promise完成,拿到所有结果 finalData = await Promise.all(findPromises); console.log(finalData); // 此时已经有完整的用户信息 } ctx.result = finalData; console.log(ctx.result); // 现在能正确输出结果了 } next(); });
关键说明:
- async/await简化异步流程:将afterRemote的处理函数标记为
async,这样我们可以用await等待Promise.all的结果,避免嵌套回调的回调地狱。 - Promise.all的作用:它会接收一个Promise数组,等待所有Promise都成功resolve后,返回一个包含所有结果的数组,顺序和原Promise数组一致。
- 替换forEach为map:map可以直接生成Promise数组,比forEach手动push更简洁高效。
如果你的Loopback版本不支持模型方法返回Promise,也可以手动将回调式的findById包装成Promise:
function findModelById(id, options) { return new Promise((resolve, reject) => { Model.findById(id, options, (err, response) => { if (err) reject(err); else resolve(response); }); }); }
然后在map里调用这个包装后的函数即可。
内容的提问来源于stack exchange,提问作者Shades
相关产品推荐
相关产品推荐

