为了账号安全,请及时绑定邮箱和手机立即绑定

我怎样才能等待循环完成?

我怎样才能等待循环完成?

牛魔王的故事 2022-11-27 16:18:39
让我首先向您展示代码的样子 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!* }       console.log() 在 for 循环完成其工作之前运行。如何运行与 console.log() 同步的“for 循环”?
查看完整描述

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);

    });

});


查看完整回答
反对 回复 2022-11-27
?
慕尼黑5688855

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);


查看完整回答
反对 回复 2022-11-27
  • 2 回答
  • 0 关注
  • 73 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信