NodeJS - Вложенное обещание внутри цикла for - PullRequest
1 голос
/ 30 мая 2020

Я пытаюсь позвонить, чтобы получить список категорий. Внутри этого вызова я хочу l oop по категориям, извлекать элементы для каждой категории и возвращать их все вместе. Мой вызов отлично извлекает категории, прежде чем я добавил l oop для извлечения элементов.

Чтобы дважды проверить, работает ли мой вызов другого контроллера, я добавил доказательство концептуального блока кода, который вы можете видеть ниже: закомментирован. Итак, я знаю, что это не вызов внешнего класса.

Вот мой код:

'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));
})

Он никогда не записывает подэлементы в объект. Это проблема asyn c или что-то еще? Я не знаю, как это решить.

Заранее спасибо.

1 Ответ

0 голосов
/ 30 мая 2020

Я считаю, что причина, по которой результат вашего вызова для разрешения возвращается до того, как запросы могут быть выполнены ... для этого вам нужно подождать, пока все обещания или запросы не завершатся должным образом и не вернутся.

Есть два способа сделать это: вы можете запускать их один за другим и ждать, пока каждый из них сначала завершит sh, или запускать их все одновременно, пока все они не будут выполнены.

Конечно, самый быстрый способ сделать это - запустить их все одновременно, поэтому давайте go для этого:

чтобы начать, давайте не будем использовать for l oop и вместо этого переназначим повторяющийся массив menuCategories на обещания запрос, мы будем использовать ваш код подтверждения концепции, чтобы создать массив обещаний

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

Надеюсь, это сработает, спасибо. ..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...