NodeJS - for 循环中的嵌套承诺



我正在尝试进行检索类别列表的调用。在此调用中,我想遍历类别并检索每个类别的项目并将它们一起返回。在我添加循环以检索项目之前,我的调用会完美地检索类别。

为了仔细检查我对另一个控制器的调用是否有效,我添加了一个概念验证代码块,您可以在下面看到它被注释掉了。所以我知道这不是对外部类的调用。

这是我的代码:

'use strict';
var mongoose = require('mongoose'),
MenuCategory = mongoose.model('MenuCategory');
module.exports = function(menuItemController) {
var mod = {
listEntireMenu(req, res) {
return new Promise(function(resolve, reject) {
var entireMenu = [];
MenuCategory.find({}, function(err, menuCategories) {
if (err) {
return reject(err)
} else {
//---------------------------
// PROOF OF CONCEPT THAT CALL TO OTHER CONTROLLER WORKS
//---------------------------
//
// var categoryWithItems = menuCategories[0].toObject();
// req.body.menuCategoryID = categoryWithItems._id;
// menuItemController.listAllMenuItemsByCategory(req, res).then((menuItems) => {
//   if(menuItems)
//   {
//     return resolve(menuItems);
//   }
//   else
//   {
//     return { success: false }
//   }
// });
//-----------------------------
for (var i = 0; i < menuCategories.length; i++) {
var categoryWithItems = menuCategories[i].toObject();
var subItems = [];
req.body.menuCategoryID = categoryWithItems._id;
menuItemController.listAllMenuItemsByCategory(req, res).then((menuItems) => {
if(menuItems)
{
subItems = menuItems;
}
else
{
return { success: false }
}
});
categoryWithItems.tester = { "itemsList" : subItems };
entireMenu.push(categoryWithItems);
}
return resolve(entireMenu)
}
});
}).then((menuCategories) => {
if(menuCategories)
{
return menuCategories
}
else
{
return { success: false }
}
});
},
}
return mod;
};

我实际得到的回报是这样的:

[
{
"_id": "5ed16fxxxxxxxx95676e37",
"locationID": "5ed16xxxxxxxx7295676e36",
"menuCategoryName": "Category One",
"Created_date": "2020-05-29T20:26:34.991Z",
"__v": 0,
"tester": {
"itemsList": []
}
},
{
"_id": "5ed170xxxxxx95676e38",
"locationID": "5ed16xxxxxxxx7295676e36",
"menuCategoryName": "Category Two",
"Created_date": "2020-05-29T20:26:48.799Z",
"__v": 0,
"tester": {
"itemsList": []
}
}
]

这是来自路由的呼叫.js :

app.get('/api/listEntireMenu', (req, res) => {
menuCategoryController.listEntireMenu(req, res).then(menuCategories => res.json(menuCategories));
})

它从不将子项写入对象。这是异步问题还是其他问题?我不确定如何解决这个问题。

提前谢谢。

我相信您的解析调用结果在请求能够完成之前返回的原因......为此,您需要等到所有承诺或请求正确完成并返回。

有两种方法可以做到这一点:您可以逐个运行它们并等待每个首先完成,或者同时运行它们,直到所有操作都完成。

当然,最快的方法是同时运行它们,所以让我们这样做:

所以首先,让我们不使用 for 循环,而是将可迭代数组菜单类别重新映射到请求的承诺,我们将使用您的概念验证代码来制作承诺数组

//...
Promise.all(
menuCategories.map((category) => {
let category_with_items = category.toObject();
req.body.menuCategoryID = category_with_items._id;
// here we need to return this since its the promise we are remapping to
return menuItemController.listAllMenuItemsByCategory(req, res)
.then((menuitems) => {
if(menuItems) {
return menuitems;
}
throw 'No menu items found'
});
});
)
// each promise will return menuitems so we have to wait for all the promises to complete
// then with the results of each promise we push the items into the entire menu
.then((itemslist) => {
itemslist.forEach((items) => entireMenu.push(items));
return entireMenu;
})
// lastly we need to handle any errors from the promises
.catch((error) => { success: false });
//...

所以现在我们有...

listEntireMenu(req, res) {
return MenuCategory.find({}, function(err, menuCategories) {
if (err) {
throw err
} else {
entireMenu = [];
return /* the promise all call from above will go right here */;
}
}

我希望它能成功,谢谢...

最新更新