Node+Angular项目then链提前返回空数组,如何让for循环填充数据后再返回
问题原因
你遇到的现象本质是异步任务执行顺序问题:JavaScript 中的异步 IO 操作(比如你的数据库查询 Template.findByTemplateId)不会阻塞同步代码执行,for 循环只是提交了所有的异步查询任务,不会等待任务返回结果就会直接执行后续的 .then 逻辑,此时 realTemps 还没有被填充,所以返回空数组。
解决方案
使用 Promise.all 批量等待所有异步查询完成后再返回结果,修改后的代码如下:
router.get("", (req, res, next) => { const token = req.headers.authorization.split(" "); const decoded = jwt.verify(token[1], 'secretkey'); const decodedFactoryId = decoded.factoryId; let templates = []; Template.findAllByFactoryId(decodedFactoryId) .then((results) => { for (var i = 0; i < results.length; i++) { // THIS IS AN AVOIDABLE LOOP, quadratic time must be prevented by correctly formatting the data (TODO) for (var j = 0; j < results.length; j++) { if (results[i][j].id) { templates.push(results[i][j].id) } } } }) .then(() => { console.log("templates: " + templates) // 把所有异步查询任务包装成Promise数组 const queryPromises = templates.map(templateId => { return Template.findByTemplateId(templateId).then(result => { console.log("here is the result: " + JSON.stringify(result[0])) return result; }) }) // 返回Promise.all,等待所有查询完成后才会进入下一个then return Promise.all(queryPromises); }) .then((realTemps) => { // 所有查询完成,realTemps就是所有结果组成的数组,直接返回给前端 res.send(realTemps); }) .catch(err => { // 错误捕获,避免接口无响应 next(err); }) })
补充说明
Promise.all会并行执行所有传入的 Promise 任务,等到所有任务都成功返回后,才会将结果按顺序组装成数组传给下一个.then,刚好匹配你的需求- 只要有一个查询失败,
Promise.all会直接触发 catch 逻辑,方便统一处理异常
内容的提问来源于stack exchange,提问作者xxcapzxx
相关产品推荐
相关产品推荐

