1

How can I await a result inside a map function where getFooBar returns an observable?

Ex code:

this.fooBarResponse.fooBars.map(async (x) => {
      x.fooBar = await this.fooBarService
        .getFooBar(x.fooBarId.toString())
        .toPromise();

      return x;
    });

foobar.service.ts

getFooBar(id: string): Observable<FooBar> {
    return this.fooBarsCollection.doc<FooBar>(id).valueChanges();
}
millerg
  • 25
  • 8

2 Answers2

0

Array#map is synchronous. Use a for...of loop instead.

for(const x of this.fooBarResponse.fooBars){
    x.fooBar = await this.fooBarService
        .getFooBar(x.fooBarId.toString())
        .pipe(take(1))
        .toPromise();
}
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
  • That doesn't seem to work either for me. However, it works when I loop over it and subscribe to getFooBar but doesn't solve the problem of retrieving the result for x.fooBar. – millerg Jul 11 '20 at 05:02
  • Here's what my getFooBar method looks like, I'm using firestore ```getFooBar(id: string): Observable { return this.fooBarsCollection.doc(id).valueChanges(); }``` – millerg Jul 11 '20 at 05:09
  • I'm not sure what you're returning there. – Unmitigated Jul 11 '20 at 05:10
  • `(method) AngularFirestoreDocument.valueChanges(): Observable` – millerg Jul 11 '20 at 05:13
  • https://stackoverflow.com/a/51677415/10733081 seemed to resolve it – millerg Jul 11 '20 at 05:19
0

Reduce your array of fooBars to a single observable that switchMap from one to the next

const { of } = rxjs;
const { switchMap, delay } = rxjs.operators;

const fooBarResponse = {
  fooBars: [{ fooBarId: 1 }, { fooBarId: 2 }, { fooBarId: 3 }, { fooBarId: 4 }, { fooBarId: 5 }, { fooBarId: 6 } ,{ fooBarId: 7 } , { fooBarId: 8 }]
}

const fooBarService = {
  getFooBar: x => of(`emitted ${x}`).pipe(delay(500))
};

fooBarResponse.fooBars.reduce(
  (obs$, x) => obs$.pipe(
    switchMap(_ => {
      console.log(`Switching from foobar ${x.fooBarId}`);
      return fooBarService.getFooBar(x.fooBarId.toString());
    })
  ),
  of(null) // start with some random observable
).subscribe(finalEmit => {
  console.log(finalEmit);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.6.0/rxjs.umd.min.js"></script>
Adrian Brand
  • 20,384
  • 4
  • 39
  • 60