Search code examples
angularfirebasegoogle-cloud-firestoreangularfire2

Firebase Doc's ARRAY field is empty upon insert


I have a very simple flow which fetch (list) all staff, then loop them and upon looping each user, insert into another firebase doc

  async insertAchivementTest() {
    let eeRef = this.afStore.collection<any>(`.../EmpSnapshot`).ref
    let eeDoc: any = eeRef
    eeDoc = eeDoc.where("employment.event", "not-in", ["TER", "RSG"])  // only active staff

    await eeDoc.get().then(async res => {
      for (let ee of res.docs) {            // loop active EE
        console.log(`proc ee = ${ee.id}`)

        // each emp, loop find evaluators
        let eeEvaluators = [] // array of object

        let formEvaluators = [{ type: 'BY_ROLE', role: '_DIRECT_REPORT_' }]
        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: ['A', 'B'],
          evaluators: eeEvaluators,
        }
        console.log('show achievement before insert...=', achievementData)
        await this.afStore.collection(`.../Collection/Achievements`)
          .ref
          .add(achievementData)
      }
    })
  }

To ensure the correct data are fetched and insert into new doc, i have console.log them BEFORE insert as firebase doc (check the console log screenshot below) enter image description here ARRAY variable eeEvaluators is an array of object, it contain a field 'evaluators' with value shown in console log. But how come every time it tries to store into firebase doc via .add(...), the field 'evaluators' is always an empty array?

note: i am using angularfire package

// Firebase package
import {
    AngularFirestore,
    AngularFirestoreCollection
} from "@angular/fire/firestore";
import { AngularFireStorage } from "@angular/fire/storage";

updates 20 May 8AM: I spotted the weird behaviour, if i move out the retrieval logic from loop, it does insert into doc correctly. Can't find any weirdo in the loop logic. Somemore, the loop is jz LOOP-ONCE as u see the logic. I am PRETTY-MUCH confirmed the weird behavior caused by the loop, but i have to have a loop to support my business logic.

        // let formEvaluators = [{ type: 'BY_ROLE', role: '_DIRECT_REPORT_' }]
        // formEvaluators.forEach(async ev => {
        //     await this.afStore.doc<any>(`...udion.com`).ref.get().then(resUser => {
        //         eeEvaluators.push(resUser.data())
        //     })
        // })

        // CHANGE TO following code (no loop)
        await this.afStore.doc<any>(`...udion.com`).ref.get().then(resUser => {
                eeEvaluators.push(resUser.data())
            })

enter image description here

update 20 May 1140AM: I found the explanation here, forEach doesn't work well for async/await, https://stackoverflow.com/a/37576787/8163746 so i replaced

formEvaluators.forEach(async ev => {

with

for (const ev of formEvaluators) 

in my code and it jz work!


Solution

  • I found the explanation here, forEach doesn't work well for async/await, https://stackoverflow.com/a/37576787/8163746 so I replaced

    formEvaluators.forEach(async ev => {
    

    with

    for (const ev of formEvaluators) 
    

    in my code and it just works!