做出承诺等待另一个承诺

时间:2018-07-28 10:05:03

标签: javascript node.js promise

在node.js应用程序中,我试图从API查找产品列表,然后仅获取第一项的缩略图。

在我的代码中,getOrderDetails是一个promise,然后,如果它是第一个产品,它将调用函数getImage,这也是一个promise。

但是,当我运行代码时,orderDetails会被填充而不会显示缩略图-因此,看起来代码没有等待getImage函数解析。

请有人能解释我做错了吗?

提前谢谢!

if (siteConfig.storeIntegration == 'Cart') {

    getOrderDetails(restPathOrder)
    .then(function(res) {

        var orderDetails = '';

        for (i = 0; i < res.items.length; i++) {

            productId = res.items[i]['productId'];

            thumbnail = '';

            if (i == 0) {

                getImage(productId, restApiKey)
                .then(function(res) {

                    thumbnail = res;

                    console.log('thumbnail:' + res);
                })
            }

            orderDetails = orderDetails + res.items[i]['quantity'] + ',' + res.items[i]['name'] + ',' + productUrl + ',' + thumbnail;

        }

        console.log(orderDetails);

    })


}

function getOrderDetails(restPath) {

    return new Promise((resolve, reject) => {

        request(restPath, function (error, response, body) {

            if (!error && response.statusCode == 200) {

                restData = JSON.parse(body);

                resolve(restData)
             }
        })
    })


}

function getImage(productId, restApiKey) {

    return new Promise((resolve, reject) => {

        var restPathProduct = storeURL + restApiKey + productId;

        request(restPathProduct, function (error, response, body) {

            if (!error && response.statusCode == 200) {

                restData = JSON.parse(body);

                thumbnail = restData.image[0];

                resolve(thumbnail);
             }
        })
    })

}

2 个答案:

答案 0 :(得分:1)

我建议使用新的await语法吗?

async main() {
    if (siteConfig.storeIntegration == 'Cart') {
        let res = await getOrderDetails(restPathOrder);

        var orderDetails = '';

        for (i = 0; i < res.items.length; i++) {

            productId = res.items[i]['productId'];

            let thumbnail = '';

            if (i == 0) {
                thumbnail = await getImage(productId, restApiKey);
            }

            orderDetails += res.items[i]['quantity'] + ',' + res.items[i]['name'] + ',' + productUrl + ',' + thumbnail;
        }
        console.log(orderDetails);
    }
}

答案 1 :(得分:1)

@FrankerZ是正确的,异步/等待使代码更简洁。

我不确定productUrl来自何处的业务逻辑。

解决方案是将整个代码块包装在一个promise中,获取第一个订单的图片,然后在getImage的then中处理订单的详细信息。

这是我的尝试,但有一些小的重构。希望它可以引导您朝正确的方向发展。

function process() {
  // Wrap everything inside a promise, we then resolve with the order details
  // Resolve is what gets returned in the .then((resolvedData)), reject is what gets returned in the .catch((rejectedThings))
  return new Promise((resolve, reject) => {

    // Get the order details
    getOrderDetails(restPathOrder)
      .then(function(orderRes) {

        // Handle no items
        if (!orderRes.items || orderRes.items.length === 0) {
          return reject("No items") // You can deal with this in the catch
        }
        // Get first item 
        const firstOrder = orderRes.items[0];

        // Fetch the first thumbnail then proceed to fetch the rest of the order details. 
        getImage(firstOrder.productId, restApiKey)
          .then(function(thumbnail) {

            let orderDetails = '';
            // Build order details body
            // N.B I'm not sure how you want orderDetails to appear, personally I would use a map instead of a forEach. 
            orderRes.items.forEach((item) => {
              orderDetails = orderDetails + item.quantity + ',' + item.name + ',' + productUrl + ',' + thumbnail;
            })

            // Then resolve with the order details
            return resolve(orderDetails);
          })
      })
  })
}

// You can then call process as a promise with the order details
process().then(function(orderDetails) => console.log(orderDetails))