Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Firestore with Await

After looking at this answer I tried to use async/await with a firestore call but I think I am missing something.

I am trying to use Snapshot to get a collection of 'hex' documents for a hex grid. (I had valueChanges working but then realized I'm going to need metadata) I want to get the hexes, then sort them into rows, and finally return them to the component. I can see that it is returning before the snapshot and pipe actions are completed as it is empty "hexRows['test']" being console logged out as "true".

TS:

Service:

async getHexesInRows(){
    let hexRows = {test: true}
    this.hexCollection = this.db.collection('hexes', ref=> ref.orderBy('id').limit(5))

this.hexes = await this.hexCollection
  .snapshotChanges()
  .pipe(
    map(actions => actions.map( hex => {
      const data = hex.payload.doc.data()
      const uid = hex.payload.doc.id
      return {uid, ...data}
    })),
    map(data => {
      data.forEach((hex, index) => {
        let rowNum = Math.floor(index / 10)
        hexRows = {test: false}

        if(hexRows[`row${rowNum}`] == undefined){
          hexRows[`row${rowNum}`] = []
        }
        hexRows[`row${rowNum}`].push(hex)
      })
      return data
    })
  )
console.log('Rows', hexRows);
console.log('Hexes', this.hexes);

return hexRows
  }

Component

hexRows: any

  constructor(public dialog: MatDialog, public afs: FirestoreService) { }
  ngOnInit() {
    this.hexRows = this.afs.getHexesInRows()
  }
like image 464
av0000 Avatar asked Dec 06 '25 05:12

av0000


1 Answers

You can't await an Observable like a Promise, instead you subscribe to the Observable where you need the data from the Observable. You usually return Observables from your Services and subscribe to them in your Components.

Return an Observable from your Service

getHexesInRows(){
  this.hexCollection = this.db.collection('hexes', ref => ref.orderBy('id').limit(5))

  return this.hexCollection
    .snapshotChanges()
    .pipe(
      map(actions => actions.map( hex => {
        const data = hex.payload.doc.data()
        const uid = hex.payload.doc.id
        return {uid, ...data}
      })),
      map(data => {
        let hexRows = {test: true}
        data.forEach((hex, index) => {
          let rowNum = Math.floor(index / 10)
          hexRows = {test: false}

          if(hexRows[`row${rowNum}`] == undefined){
            hexRows[`row${rowNum}`] = []
          }
          hexRows[`row${rowNum}`].push(hex)
        })
        return hexRows
      }),
      // tap(hexRows => this.hexRows = hexRows), // if you need the hexes in your Service but you usually shouldn't
      tap(hexRows => console.log('Rows', hexRows)) // if you want to log something in your Service
    );
}

Subscribe to the Observable in your Component

hexRows: any

constructor(public dialog: MatDialog, public afs: FirestoreService) { }

ngOnInit() {
  this.afs.getHexesInRows().subscribe(hexes => this.hexRows = hexes);
}
like image 166
frido Avatar answered Dec 08 '25 17:12

frido