让我首先向您展示代码是什么样子的
Cart.getCompleteCart((cart)=>{
let products = []; *//this Array has to be filled*
totalPrice = cart.totalPrice;
for(let prod of cart.products){
Product.getProductDetails(prod.productId, productDetails => {
products.push({
product: productDetails,
productCount: prod.productCount
});
});
}
console.log("Products are ->", products); *//this line is running before for loop!*
}
在for循环完成其工作之前,console.log()正在运行。
如何与console.log()同步运行“for循环”?
我假设product.getProductDetails()
是一个异步方法(它看起来像是对API的查询)。
console.log()
不是“在for
循环之前运行”,它只是在异步处理Product.GetProductDetails()
执行的任务。
由于Product.getProductDetails()
方法似乎也可以用于回调,因此实现目标的一种方法是允诺每个调用,然后使用Product.all()
方法将所有允诺压缩为一个单独的允诺。
像这样的方法应该能奏效:
Cart.getCompleteCart((cart) => {
const promises = [];
for (let prod of cart.products) {
promises.push(
new Promise((resolve) => {
Product.getProductDetails(prod.productId, (productDetails) => {
resolve({
product: productDetails,
productCount: prod.productCount
});
});
})
);
}
Promise.all(promises).then((products) => {
console.log('Products are ->', products);
});
});
或者:
Cart.getCompleteCart((cart) => {
Promise.all(
cart.products.map((prod) => {
return new Promise((resolve) => {
Product.getProductDetails(prod.productId, (productDetails) => {
resolve({
product: productDetails,
productCount: prod.productCount
});
});
});
})
).then((products) => {
console.log('Products are ->', products);
});
});
Promise.all
几乎是为这种确切的用例设计的:
null
// A dummy "Product" with a dummy "getProductDetails" implementation
// so that we can have a working test example
let Product = {
getProductDetails: (productId, callback) => {
setTimeout(() => {
callback({ type: 'productDetails', productId });
}, 100 + Math.floor(Math.random() * 200));
}
};
// This is the function you're looking for:
let getCompleteCart = async (cart) => {
return Promise.all(cart.products.map(async ({ productId, productCount }) => ({
product: await new Promise(resolve => Product.getProductDetails(productId, resolve)),
productCount
})));
}
let exampleCart = {
products: [
{ productId: 982, productCount: 1 },
{ productId: 237, productCount: 2 },
{ productId: 647, productCount: 5 }
]
};
getCompleteCart(exampleCart).then(console.log);
您可以使用async/await
构造:使您的回调为async
,然后您可以在内部使用await
运算符来模拟同步操作:
Cart.getCompleteCart(async (cart)=>{
let products = []; *//this Array has to be filled*
totalPrice = cart.totalPrice;
for(let prod of cart.products){
await Product.getProductDetails(prod.productId, productDetails => {
products.push({
product: productDetails,
productCount: prod.productCount
});
});
}
console.log("Products are ->", products);
}