【问题标题】:NodeJS - Nested Promise inside a for loopNodeJS - for 循环内的嵌套 Promise
【发布时间】:2020-09-17 16:34:09
【问题描述】:

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

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

这是我的代码:

'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": []
        }
    }
]

这是来自 route.js 的调用:

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

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

提前致谢。

【问题讨论】:

    标签: node.js api express server promise


    【解决方案1】:

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

    您可以通过两种方式执行此操作:您可以一个一个地运行它们并等待每个先完成,或者同时运行它们直到所有它们都完成。

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

    首先,让我们不要使用 for 循环,而是将可迭代数组 menuCategories 重新映射到请求的 Promise,我们将使用您的概念证明代码来制作 Promise 数组

    //...
    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 */;
        }
    }
    

    希望能成功,谢谢...

    【讨论】:

    • 我还没有设法让它工作。我认为这是因为我的路线期望解析返回数据。我始终使用解决方案,但似乎无法使其与您建议的 Promise.all 一起使用。
    猜你喜欢
    • 1970-01-01
    • 2017-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 2018-10-01
    • 1970-01-01
    相关资源
    最近更新 更多