2 回答
TA贡献1811条经验 获得超5个赞
我假设这Product.getProductDetails()是一个异步方法(它看起来像是对 API 的查询)。
console.log()不是“在for循环之前运行”,只是执行的任务Product.getProductDetails()正在异步处理。
由于该方法似乎也适用于回调,因此实现您的目标的一种方法是对每个调用进行承诺,然后通过使用方法Product.getProductDetails()将所有承诺压缩为一个承诺。Promise.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);
});
});
TA贡献1848条经验 获得超2个赞
Promise.all几乎是为这个确切的用例而设计的:
// 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);
细分getCompleteCart:
let getCompleteCart = async (cart) => {
return Promise.all(cart.products.map(async ({ productId, productCount }) => ({
product: await new Promise(resolve => Product.getProductDetails(productId, resolve)),
productCount
})));
}
Promise.all( mdn ) 是专门为等待承诺数组中的每一个承诺而构建的
我们需要提供一个 Promise 数组给Promise.all. 这意味着我们需要将数据数组 ( cart.products) 转换为 Promises 数组;Array.protoype.map是这方面的完美工具。
提供的函数cart.products.map将购物车中的每个产品转换为看起来像的对象{ product: <product details>, productCount: <###> }。
这里棘手的事情是获取“product”属性的值,因为这个值是异步的(由回调返回)。Product.getProductDetails以下行使用 Promise 构造函数 ( mdn )创建一个解析为由 返回的值的promise :
new Promise(resolve => Product.getProductDetails(productId, resolve))
await关键字允许我们将此承诺转换为它产生的未来值。我们可以将此未来值分配给“product”属性,而“productCount”属性只是从购物车中的原始商品复制而来:
{
product: await new Promise(resolve => Product.getProductDetails(productId, resolve)),
productCount
}
为了console.log在正确的时间运行,我们需要等待所有产品详细信息完成编译。幸运的是,这是由getCompleteCart. 我们可以console.log在适当的时候通过等待getCompleteCart来解决。
有两种方法可以做到这一点:
使用Promise.prototype.then(mdn):
getCompleteCart(exampleCart).then(console.log);
或者,如果我们在async上下文中,我们可以使用await:
let results = await getCompleteCart(exampleCart);
console.log(results);
添加回答
举报