提问者:小点点

我如何才能等待循环完成?


让我首先向您展示代码是什么样子的

 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循环”?


共3个答案

匿名用户

我假设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); 

}