我创建了一个名为(using bluebird)
的承诺函数getBasketObject
。此函数需要一个篮子作为参数,而不是从中返回一个新的basketObject
。
basketObject
包含tax, total, shipping
和productItems
等变量。现在,productItems对象中有price, name, quantity
个属性,但它没有productImageLink
可用。
为了获得productImageLink
我对端点进行新的异步调用,这将获得产品图像对象。 Image Endpoint
也是作为承诺实现的。
现在,我遍历productLineItems
并获取name, price, quantity
等属性的值,最后调用get image。
现在,如果我添加
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
有多个产品
答案 0 :(得分:1)
首先,您的resolve(basketObj)
无效,因为您为Promise多次致电resolve
,但您必须只拨打一次。
你也应该避免使用string
作为错误,但总是使用真正的错误(不仅是使用promises而且是javascript中的所有时间)。
您可以在Promise链中传递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;
});
};
答案 1 :(得分:1)
循环未完成,因为您在第一次迭代时解决了您的承诺。但是您需要等待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)
确实进行了异步调用