Javascript 如何等待forEach完成,然后再从我的承诺/功能返回

Javascript 如何等待forEach完成,然后再从我的承诺/功能返回,javascript,google-cloud-firestore,promise,Javascript,Google Cloud Firestore,Promise,火库 我有一个角度函数从一个firestore集合中获取产品,然后我循环该查询的结果以查找另一个集合中的价格 在从外部承诺和外部功能本身返回之前,我怎么能等到每个的价格都完成了呢 返回的结果包含products数组,但每个产品的prices数组为空 const products = await this.billingService.getProducts(); 我也尝试过这种方法,但不确定如何访问结果 await this.billingService.getProducts().then

火库

我有一个角度函数从一个firestore集合中获取产品,然后我循环该查询的结果以查找另一个集合中的价格

在从外部承诺和外部功能本身返回之前,我怎么能等到每个的价格都完成了呢

返回的结果包含products数组,但每个产品的prices数组为空

 const products = await this.billingService.getProducts();
我也尝试过这种方法,但不确定如何访问结果

await this.billingService.getProducts().then(results =>
让getProducts()函数成为承诺。因此,只有在您解决(或拒绝)它时,它才会返回

然后你可以使用Then或Wait调用承诺

this.billingService.getProducts().then( res => {
 const products = res;
})
使用等待

const products = await this.billingService.getProducts();

以社区维基答案发布,基于评论


在这种情况下,使用
forEach()
不是正确的选择。正如在本例中所阐明的,
forEach()
不能与
wait
函数一起正常工作,这样一来,您的承诺就不能正常工作。考虑到这一点以及您希望按顺序读取数据的事实(因为一个查询的结果将影响第二个查询的结果),您需要为使用一个普通的
,以循环数据和数组。这个具体的答案应该可以帮助您获得代码示例。

这个版本的代码可以:

  getProducts(): Promise<any> {
    return new Promise((resolve,reject)=> {
      let result = [];
      let product = {};
      this.db.collection(
        'products',
        ref => { ref
          let query: Query = ref;
          return query.where('active', '==', true)
        })
        .ref
        .get()
        .then(async function (querySnapshot:firebase.firestore.QuerySnapshot) {
          for(const doc of querySnapshot.docs) {
            const priceSnap = await doc.ref
              .collection('prices')
              .orderBy('unit_amount')
              .get()
            product = doc.data();
            product['prices'] = [];
            // Prices dropdown
            for(const doc of priceSnap.docs) {
              const priceId = doc.id;
              let priceData = doc.data();
              priceData['price_id'] = priceId;
              product['prices'].push(priceData);
              resolve(result);// returns when it reaches here
            };
            result.push(product);
          };
        });
    })
  }
getProducts():承诺{
返回新承诺((解决、拒绝)=>{
让结果=[];
设乘积={};
此为.db.collection(
"产品",,
ref=>{ref
let query:query=ref;
返回查询。其中('active','=',true)
})
参考号
.get()
.then(异步函数(querySnapshot:firebase.firestore.querySnapshot){
for(querySnapshot.docs的const doc){
const priceSnap=wait doc.ref
.收款(“价格”)
.orderBy(“单位金额”)
.get()
product=doc.data();
产品['价格]=[];
//价格下跌
用于(priceSnap.docs的常量文档){
const priceId=doc.id;
让priceData=doc.data();
priceData['price_id']=priceId;
产品['prices'].push(价格数据);
resolve(result);//到达此处时返回
};
结果:推送(产品);
};
});
})
}

async/await在forEach循环中的工作方式与预期不同。停止使用
.forEach()
。它不是异步的或承诺感知的。对
循环intead使用常规的
。@jfriend00
for(querySnapshot的const doc){
类型“querySnapshot”必须有一个“[Symbol.iterator]”方法,该方法返回迭代器.ts(2488)@dak-
querySnapshot.docs
是一个你应该可以使用的数组。请看。有多个问题。我只是表示他可以使用承诺来完成。他只需要在正确的位置解决问题。谢谢你指出问题。
this.billingService.getProducts().then( res => {
 const products = res;
})
const products = await this.billingService.getProducts();
  getProducts(): Promise<any> {
    return new Promise((resolve,reject)=> {
      let result = [];
      let product = {};
      this.db.collection(
        'products',
        ref => { ref
          let query: Query = ref;
          return query.where('active', '==', true)
        })
        .ref
        .get()
        .then(async function (querySnapshot:firebase.firestore.QuerySnapshot) {
          for(const doc of querySnapshot.docs) {
            const priceSnap = await doc.ref
              .collection('prices')
              .orderBy('unit_amount')
              .get()
            product = doc.data();
            product['prices'] = [];
            // Prices dropdown
            for(const doc of priceSnap.docs) {
              const priceId = doc.id;
              let priceData = doc.data();
              priceData['price_id'] = priceId;
              product['prices'].push(priceData);
              resolve(result);// returns when it reaches here
            };
            result.push(product);
          };
        });
    })
  }