使用AngularFire向Firebase插入文档时evaluators数组字段为空的问题排查与解决
问题分析与解决方案:Firebase插入时异步数组字段为空
问题场景
你基于AngularFire实现了一套业务流程:从Firebase获取在职员工数据,遍历每位员工异步获取其评估人列表,最终将包含评估人信息的数据插入到另一个集合中。但遇到了一个诡异的问题:插入前console.log明明显示eeEvaluators有预期的对象数据,可Firebase文档里的evaluators字段却始终是空数组。
核心问题代码片段:
async insertAchivementTest() { let eeRef = this.afStore.collection<any>(`.../EmpSnapshot`).ref let eeDoc = eeRef.where("employment.event", "not-in", ["TER", "RSG"]) await eeDoc.get().then(async res => { for (let ee of res.docs) { let eeEvaluators = [] let formEvaluators = [{ type: 'BY_ROLE', role: '_DIRECT_REPORT_' }] // 此处的forEach+async/await是问题核心 formEvaluators.forEach(async ev => { await this.afStore.doc<any>(`...udion.com`).ref.get().then(res => { eeEvaluators.push(res.data()) }) }) let achievementData = { email: ee.id, evaluators: eeEvaluators, } await this.afStore.collection(`.../Collection/Achievements`).ref.add(achievementData) } }) }
问题根源
forEach方法本身并不兼容async/await的异步等待逻辑。当你在forEach的回调函数里使用async时,forEach会快速遍历执行所有回调,但不会等待每个异步操作完成就继续执行后续代码。也就是说,在你调用add(achievementData)插入数据时,eeEvaluators的异步填充操作还没完成,此时数组还是空的,自然插入到Firebase的就是空数组。
你也发现了,去掉循环直接执行单次异步操作时能正常工作,这是因为没有forEach的干扰,await能正确等待异步操作完成后再执行后续代码。
解决方案
把forEach替换成支持async/await的for...of循环,这样就能保证每个异步操作完成后再进行下一次循环,确保eeEvaluators在完全填充后才被用于数据插入:
优化后的代码片段:
async insertAchivementTest() { let eeRef = this.afStore.collection<any>(`.../EmpSnapshot`).ref let eeDoc = eeRef.where("employment.event", "not-in", ["TER", "RSG"]) // 建议用await替代then,让异步逻辑更清晰 const res = await eeDoc.get(); for (let ee of res.docs) { let eeEvaluators = [] let formEvaluators = [{ type: 'BY_ROLE', role: '_DIRECT_REPORT_' }] // 替换forEach为for...of for (const ev of formEvaluators) { const resUser = await this.afStore.doc<any>(`...udion.com`).ref.get(); eeEvaluators.push(resUser.data()); } let achievementData = { email: ee.id, evaluators: eeEvaluators, } console.log('show achievement before insert...=', achievementData) await this.afStore.collection(`.../Collection/Achievements`).ref.add(achievementData) } }
额外建议:尽量避免await和then混合使用,像上面那样把链式then改成直接await,代码的可读性和异步逻辑的清晰度会大幅提升。
内容的提问来源于stack exchange,提问作者Weilies
相关产品推荐
相关产品推荐

