Javascript 在执行代码之前,等待所有Firebase数据查询请求
在我处理数据并将其应用于批处理之前,我试图提前从我的cloud Firestore数据库中的不同集合中获取数据,我创建了两个异步函数,一个用于捕获数据,另一个用于仅在收集完所有数据后执行某些代码,我不希望代码在获取数据之前执行和创建错误,当我尝试在异步函数收集数据完成后访问MatcheObject时,它一直说“它无法访问未定义的属性matchStatus”,我想用async和Wait解决了这个问题?有人能解释一下为什么它在某一时刻是未定义的吗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
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。另外,通过记录它们,如果它最终是数据库中数百个文档中的一个文档,那么它应该有助于找到问题所在。