[英]How to call Promise function in loop and save its return value
我創建了一個承諾函數(using bluebird)
稱為getBasketObject
。 此函數期望將basket作為參數,然后basketObject
返回一個新的basketObject
。
basketObject
具有一些變量,例如tax, total, shipping
和productItems
。 現在,productItems對象中具有price, name, quantity
屬性,但其中沒有productImageLink
。
為了獲得productImageLink
我對端點進行了新的異步調用,這將使我獲得產品圖像對象。 Image Endpoint
也被實現為Promise。
現在,我遍歷productLineItems
並獲取name, price, quantity
等屬性的值,最后調用以獲取圖像。
現在,如果我添加
basketObj["products"][productId]["productImageSrc"] = smallImage[0];
我的對象從未修改過,在最終輸出中我沒有圖像鏈接。
發生這種情況是因為在異步調用發生之前我的getBasketObject
返回了值。 為了解決這個問題,我添加了resolve(basketObj);
但這立即返回,並且不在循環中。
因此,遍歷我的產品並獲取所有產品的圖像鏈接的正確方法是什么。
exports.getBasketObject = function(basket) {
return new Promise(function(resolve, reject){
if (!basket){
reject("Please give valid basket");
}
var basketObj = {};
if ('order_total' in basket && basket.order_total) {
basketObj.total = basket.order_total;
} else if ('product_total' in basket && basket.product_total) {
basketObj.total = basket.product_total;
}
var productLineItems = basket.product_items;
basketObj["products"] = {};
for (var key in productLineItems) {
var productItem = productLineItems[key];
var productId = productItem.product_id;
//Async call to get Product Object
product.getProductObject(productId).then(function(productObj){
basketObj["products"][productId] = {};
basketObj["products"][productId]['productQuantity'] = productItem.quantity;
basketObj["products"][productId]["productName"] = productItem.item_text;
basketObj["products"][productId]["productPrice"] = productItem.base_price;
//If promise resolved, get images
var imageObject = product.getProductImages(productObj[0]);
var smallImage = imageObject['small'];
basketObj["products"][productId]["productImageSrc"] = smallImage[0];
resolve(basketObj); //Acts as a return
});
}
});
};
如果我使用resolve(basketObject)
我的最終對象看起來像
{
"total": 95.99,
"tax": "N/A",
"shipping": "N/A",
"products": {
"701642890706": {
"productQuantity": 1,
"productName": "Novelty Stitch Belted Cardigan",
"productPrice": 95.99,
"productImageSrc": "image.png"
}
}
}
您可以看到它僅獲得一個產品對象,即使productLineItems
具有多個產品
首先,您的resolve(basketObj)
無效,因為您多次為Promise調用resolve
,但是您只能調用一次。
您還應該避免將string
用作錯誤,而應始終使用實際錯誤(不僅使用promise,而且始終使用javascript)。
而不是你的for in
循環中,您可以通過Object.keys(productLineItems)
在你的諾言鏈,然后使用.each
而不是for in
循環。
這樣,您可以返回product.getProductObject
引入的Promise。
您可以這樣重寫它:
exports.getBasketObject = function(basket) {
var basketObj = {};
var productLineItems;
return Promise.resolve(basket)
.then(function(basket) {
if( !basket ) {
throw new Error("Please give valid basket");
}
productLineItems = basket.product_items;
})
.then(function() {
if ( 'order_total' in basket && basket.order_total) {
basketObj.total = basket.order_total;
} else if ( 'product_total' in basket && basket.product_total) {
basketObj.total = basket.product_total;
}
basketObj.products = {};
//return the all keys of the productLineItems to be able to iterate over it using promises
return Object.keys(productLineItems);
})
.each(function(key) {
var productItem = productLineItems[key];
var productId = productItem.product_id;
basketObj.products[productId] = {};
basketObj.products[productId].productQuantity = productItem.quantity;
basketObj.products[productId].productName = productItem.item_text;
basketObj.products[productId].productPrice = productItem.base_price;
//Async call to get Product Object
return product.getProductObject(productId).then(function(productObj) {
//If promise resolved, get images
var imageObject = product.getProductImages(productObj[0]);
var smallImage = imageObject.small;
basketObj.products[productId].productImageSrc = smallImage[0];
});
})
.then(function() {
// return the basketObj after all product.getProductObject resolved
return basketObj;
});
};
如果您不想使用.each
,則可以這樣編寫:
exports.getBasketObject = function(basket) {
var basketObj = {};
var productLineItems;
return Promise.resolve(basket)
.then(function(basket) {
if( !basket ) {
throw new Error("Please give valid basket");
}
productLineItems = basket.product_items;
})
.then(function() {
if ( 'order_total' in basket && basket.order_total) {
basketObj.total = basket.order_total;
} else if ( 'product_total' in basket && basket.product_total) {
basketObj.total = basket.product_total;
}
basketObj.products = {};
var promises = [];
Object.keys(productLineItems).forEach(function(key) {
var productItem = productLineItems[key];
var productId = productItem.product_id;
basketObj.products[productId] = {};
basketObj.products[productId].productQuantity = productItem.quantity;
basketObj.products[productId].productName = productItem.item_text;
basketObj.products[productId].productPrice = productItem.base_price;
promises.push(
product.getProductObject(productId).then(function(productObj) {
//If promise resolved, get images
var imageObject = product.getProductImages(productObj[0]);
var smallImage = imageObject.small;
basketObj.products[productId].productImageSrc = smallImage[0];
});
);
});
return Promise.all(promises);
})
.then(function() {
return basketObj;
});
};
循環未完成,因為您在第一次迭代中解決了諾言。 但是您需要等待product.getProductObject
所有異步調用完成。 在這里Promise.all
可以提供幫助。
...
var asycnCalls = [];
for (var index in productLineItems) {
...
//Async call to get Product Object
asyncCalls.push(
product.getProductObject(productId).then(function(productObj){
//If promise resolved, get images
var imageObject = product.getProductImages(productObj[0]);
var smallImage = imageObject['small'];
basketObj["products"][productId]["productImageSrc"] = smallImage[0];
})
)
} //end of for loop
Promise.all(asyncCalls).then(function(value) {
resolve(basketObj); //Acts as a return
}, function(reason) {
reject(reason);
});
並且請確保product.getProductObject(productId)
確實進行了異步調用
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.