首页 > 解决方案 > 在嵌套请求循环内向另一台服务器请求

问题描述

我需要从另一台服务器请求 X 产品,我需要等待该执行完成,然后再继续并将订单保存在数据库中。假设我通过 post 收到需要添加到订单中的产品 ID 数组,例如

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。如果我 console.log 产品,它们仅在 orderInstance 保存后出现。我已经尝试实现回调来解决这个问题,但没有成功。如果有人可以在这里帮助我,我将不胜感激!在此先感谢:笑脸:(已编辑)

标签: javascriptnode.jsexpress

解决方案


forEach同步运行-forEach结束时,client.get请求可能已全部发出,但响应肯定还没有回来。您需要将每个请求转换为Promise,然后调用Promise.all这些 Promise 的数组。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
  });

推荐阅读