Запрос внутри вложенного цикла запроса на другой сервер - PullRequest
0 голосов
/ 03 ноября 2018

Мне нужно запросить продукты X с другого сервера, и мне нужно дождаться завершения этого выполнения, прежде чем продолжить и сохранить заказ в базе данных. Допустим, я получил по почте массив идентификаторов продуктов, которые мне нужно добавить в заказ, например,

JSON FILE:
{
   "order_products":[1,2,3,4]
}

Вот пример кода:

//Express module
var router = require('express').Router();
//HTTP Request module
var client = require('request');
//Util that saves the URLs of the other databases
var productURL = require('../utils/product/productURL');
//Builds a product object given a JSON 
var productBuilder = require('../utils/product/productBuilder');

router.post('/', req, res) {

//Instantiate a new order
  var orderInstance = new order({
       date: Date.now
  });

//Query the products in the other server and add them to the order
  req.body.order_products.forEach(id => {
       client.get(productURL.HTTPS + id, { json: true }, (err, res, JSONProduct) => {
                var product = productBuilder.build(JSONProduct);
                orderInstance.order_products.push(product);
      });
  };

//Save the order in the database
  orderInstance.save(....);

//Send response
  res.status(201).json(orderInstance);
}

Проблема здесь в том, что, пока цикл все еще выполняется, ответ отправляется (201), и orderInstance сохраняется без какого-либо продукта. Если я консоль.log продукты, они появляются только после сохранения orderInstance. Я пытался реализовать обратные вызовы, чтобы исправить эту проблему, но безуспешно. Буду признателен, если кто-нибудь сможет мне помочь! Заранее спасибо: smiley: (отредактировано)

1 Ответ

0 голосов
/ 03 ноября 2018

forEach выполняется синхронно - когда forEach заканчивается, возможно, все запросы client.get были отправлены, но ответы, безусловно, еще не вернулись. Вам необходимо преобразовать каждый запрос в Promise, а затем вызвать Promise.all для массива этих обещаний. Promise.all разрешится, как только все ответы вернутся. Например:

const allPromises = req.body.order_products.map(id => new Promise((resolve, reject) => {
  client.get('productURL.HTTPS' + id, { json: true }, (err, res, JSONProduct) => {
    if (err) reject (err);
    else resolve(productBuilder.build(JSONProduct));
  });
}));
Promise.all(allPromises)
  .then((newProducts) => {
    orderInstance.order_products.push(...newProducts);
    res.status(201).json(orderInstance);
  })
  .catch((err) => {
    // handle errors
  });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...