Javascript 在执行代码之前,等待所有Firebase数据查询请求

Javascript 在执行代码之前,等待所有Firebase数据查询请求,javascript,firebase,google-cloud-firestore,async-await,Javascript,Firebase,Google Cloud Firestore,Async Await,在我处理数据并将其应用于批处理之前,我试图提前从我的cloud Firestore数据库中的不同集合中获取数据,我创建了两个异步函数,一个用于捕获数据,另一个用于仅在收集完所有数据后执行某些代码,我不希望代码在获取数据之前执行和创建错误,当我尝试在异步函数收集数据完成后访问MatcheObject时,它一直说“它无法访问未定义的属性matchStatus”,我想用async和Wait解决了这个问题?有人能解释一下为什么它在某一时刻是未定义的吗 axios.request(options).the

在我处理数据并将其应用于批处理之前,我试图提前从我的cloud Firestore数据库中的不同集合中获取数据,我创建了两个异步函数,一个用于捕获数据,另一个用于仅在收集完所有数据后执行某些代码,我不希望代码在获取数据之前执行和创建错误,当我尝试在异步函数收集数据完成后访问MatcheObject时,它一直说“它无法访问未定义的属性matchStatus”,我想用async和Wait解决了这个问题?有人能解释一下为什么它在某一时刻是未定义的吗

axios.request(options).then(function(response) {
  console.log('Total matches count :' + response.data.matches.length);

  const data = response.data;
  var matchesSnapshot;
  var marketsSnapshot;
  var tradesSnapshot;
  var betsSnapshot;

  matchesObject = {};
  marketsObject = {};
  tradesObject = {};
  betsObject = {};

  start();

  async function checkDatabase() {
    matchesSnapshot = await db.collection('matches').get();
    matchesSnapshot.forEach(doc => {
      matchesObject[doc.id] = doc.data();
      console.log('matches object: ' + doc.id.toString())
    });

    marketsSnapshot = await db.collection('markets').get();
    marketsSnapshot.forEach(doc2 => {
      marketsObject[doc2.id] = doc2.data();
      console.log('markets object: ' + doc2.id.toString())
    });

    tradesSnapshot = await db.collection('trades').get();
    tradesSnapshot.forEach(doc3 => {
      tradesObject[doc3.id] = doc3.data();
      console.log('trades object: ' + doc3.id.toString())
    });

    betsSnapshot = await db.collection('bets').get();
    betsSnapshot.forEach(doc4 => {
      betsObject[doc4.id] = doc4.data();
      console.log('bets object: ' + doc4.id.toString())
    });
  }


  async function start() {
    await checkDatabase();
    // this is the part which is undefined, it keeps saying it cant access property matchStatus of undefined
    console.log('here is matches object  ' + matchesObject['302283']['matchStatus']);

    if (Object.keys(matchesObject).length != 0) {
      for (let bets of Object.keys(betsObject)) {

        if (matchesObject[betsObject[bets]['tradeMatchId']]['matchStatus'] == 'IN_PLAY' && betsObject[bets]['matched'] == false) {
          var sfRef = db.collection('users').doc(betsObject[bets]['user']);
          batch11.set(sfRef, {
            accountBalance: admin.firestore.FieldValue + parseFloat(betsObject[bets]['stake']),
          }, {
            merge: true
          });

          var sfRef = db.collection('bets').doc(bets);
          batch12.set(sfRef, {
            tradeCancelled: true,
          }, {
            merge: true
          });
        }
      }
     
     }

    });

当前代码中的小问题太多,无法逐一调试,因此此重构引入了针对数据的各种测试。它目前不会对您的数据库进行任何更改,它将取代您的
start()
函数

与当前代码的主要区别之一是,它不会不必要地下载4个文档集(其中两个文档甚至没有在您包含的代码中使用)

台阶 首先,它将获得所有匹配了
的==false
的下注文档。从这些文档中,它将检查它们是否有语法错误,并将其报告给控制台。对于每个有效的赌注文档,它的链接比赛文档的ID将被抓取,这样我们就可以获取所有我们实际需要的比赛文档。然后,我们将对用户余额和赌注文档的更改排队。最后,我们报告要做的任何更改并提交它们(一旦您取消对该行的注释)

代码 注意:
fetchDocumentById()
是。它是一个帮助函数,允许
someCollectionRef.where(FieldPath.documentId(),'in',arrayOfIds)
一次获取10个以上的ID

异步函数applyBalanceChanges(){ const bets collectionref=db.collection('bets'); const matchesCollectionRef=db.collection('matches'); const userscolectionref=db.collection('users'); const betDataMap={};//记录 等待下注收集参考 .where('matched','=',false) .get() 。然后((快照)=>{ betsnapshot.forEach(betDoc=>{ betDataMap[betDoc.id]=betDoc.data(); }); }); const matchDataMap={};//记录 //betIdList包含将要处理的所有ID const betIdList=Object.keys(betDataMap.filter)(betId=>{ 常量betData=betDataMap[betId]; 如果(!betData){ log(`WARN:Skipped Bet},因为它是falsy(实际值:${betData})`); 返回false; } const matchId=betData.tradeMatchId; 如果(!matchId){ log(`WARN:Skipped Bet}${betId},因为它有一个错误的匹配ID(实际值:${matchId})`); 返回false; } 如果(!betData.user){ log(`WARN:Skipped Bet}${betId},因为它有一个falsy用户ID(实际值:${userId})`); 返回false; } const stakeAsNumber=Number(betData.stake);//不使用parseFloat,因为它太松散了 if(isNaN(银行账号)){ log(`WARN:Skipped#${betId},因为它有一个无效的桩值(原始NaN值:${betData.stack})`); 返回false; } matchDataMap[matchId]=undefined;//使用undefined,因为它是文档不存在时“doc.data()”的结果 返回true; }); 等待获取文档byid( matchesCollectionRef, 对象键(matchIdMap), (matchDoc)=>matchDataMap[matchDoc.id]=matchDoc.data() ); const batch=db.batch(); 常数queuedUpdates=0; betIdList.forEach(betId=>{ 常量betData=betDataMap[betId]; const matchData=matchDataMap[betData.tradeMatchId]; 如果(匹配数据===未定义){ log(`WARN:Skipped/bets/${betId},因为它的链接匹配不存在!`); 继续; } 如果(matchData.matchStatus!==“正在播放”){ log(`INFO:Skipped/bets/${betId},因为它的链接匹配状态不是“正在进行”(实际值:${matchData.matchStatus})`); 继续; } 常数betRef=betcollectionref.doc(betId); const betUserRef=usersCollectionRef.doc(betData.user); update(betUserRef,{accountBalance:admin.firestore.FieldValue.increment(Number(betData.stake))}); update(betRef,{tradeCancelled:true}); queuedUpdates+=2;//用于日志记录 }); log(`INFO:Batch当前有${queuedUpdates}排队`); //仅在准备进行更改时取消注释 //batch.commit(); } 用法:

axios.request(options)
  .then(function(response) {
    const data = response.data;

    console.log('INFO: Total matches count from API:' + data.matches.length);

    return applyBalanceChanges();
  }

该错误消息意味着
/matches/302283
不在您的数据库中。我检查了它,发现了什么问题?有一刻它未定义,有一刻它找到了值谢谢,让我试试这个,如果文档值有问题,你可以跳过,但是为什么会发生这种情况呢?@mac有正确的安全规则和验证,它们永远不应该被跳过。我没有你数据库的屏幕截图,所以我不得不做一些假设,并根据这些假设进行测试。虽然您可以假设数据是正确的,但这可能会导致危险的bug。另外,通过记录它们,如果它最终是数据库中数百个文档中的一个文档,那么它应该有助于找到问题所在。