如何等待函数返回值?异步请求填充数组为空问题求助
看起来你在处理异步Promise的时候踩了一个很常见的坑——没有等待异步操作完成就返回了结果。让我帮你理清问题并修复代码:
核心问题分析
你的findBadRail函数里,getPlacingByTN和getAllPlacings都是异步操作(返回Promise),它们的.then回调会在当前同步代码执行完之后才触发。但你在同步代码里直接返回了badRail数组,这时候异步回调还没执行,数组自然是空的。
另外,railsAvailable里用Promise.resolve(findBadRail(...))也没用,因为findBadRail返回的是一个同步生成的空数组,不是Promise,所以这个Promise会立刻resolve成空值,根本等不到异步逻辑完成。
修复方案
我们需要让findBadRail返回一个Promise,确保所有异步操作完成后再返回填充好的数组。这里有两种写法:
写法一:Promise链式调用
router.get('/newRail/:trainNumber', function (req, res) { railsAvailable(req.params.trainNumber) .then(function (placing) { res.json(placing); // 此时数组已填充完成 }) .catch(err => { // 一定要处理错误,避免请求挂起 res.status(500).json({ error: err.message }); }); }); function railsAvailable(trainNumber) { // 直接返回findBadRail的Promise即可,无需额外包装 return findBadRail(trainNumber); } function findBadRail(trainNumber) { // 链式调用Promise,避免嵌套回调 return getPlacingByTN(trainNumber) .then(placing => { const badRail = [placing.rail]; // 继续链式调用getAllPlacings return getAllPlacings().then(allPlacings => { allPlacings.forEach(p => { // 这里放入你的计算逻辑 // ... badRail.push(p.rail); }); // 异步操作全部完成,返回填充好的数组 return badRail; }); }); } function getPlacingByTN(trainNumber) { return CollectionDB.findOne({"trainNumberArr": {$eq: trainNumber}}, {}); } function getAllPlacings() { // 注意:MongoDB的find返回游标,需要转成数组才能遍历 return CollectionDB.find().toArray(); }
写法二:async/await(更易读)
如果你的Node.js环境支持ES2017+,推荐用async/await扁平化代码:
router.get('/newRail/:trainNumber', async function (req, res) { try { const placing = await railsAvailable(req.params.trainNumber); res.json(placing); } catch (err) { res.status(500).json({ error: err.message }); } }); function railsAvailable(trainNumber) { return findBadRail(trainNumber); } async function findBadRail(trainNumber) { // 等待第一个异步操作完成 const placing = await getPlacingByTN(trainNumber); const badRail = [placing.rail]; // 等待第二个异步操作完成 const allPlacings = await getAllPlacings(); // 同步遍历填充数组 allPlacings.forEach(p => { // 你的计算逻辑 // ... badRail.push(p.rail); }); return badRail; } function getPlacingByTN(trainNumber) { return CollectionDB.findOne({"trainNumberArr": {$eq: trainNumber}}, {}); } function getAllPlacings() { return CollectionDB.find().toArray(); }
关于
.then内部嵌套.then的问题 完全可行!但如果嵌套层级太多,会导致回调地狱(代码缩进越来越深,可读性和维护性下降)。所以更推荐用Promise链式调用(写法一)或者async/await(写法二)来扁平化代码结构,让逻辑更清晰。
另外提醒一点:MongoDB的find()方法返回的是游标对象,不是直接的数组,所以必须调用.toArray()才能获取可遍历的文档数组,否则forEach可能不会按预期工作。
内容的提问来源于stack exchange,提问作者Davide
相关产品推荐
相关产品推荐

