chirmac
chirmac

Reputation: 35

NgRx effect only listens to last returned observable, ignores any previous returned observable

I'm syncing my app to firestore, listening for changes. When the app starts, it immediately dispatches a couple of actions to my store, to add the documents. I also have a NgRx effect waiting for the add action to be triggered to execute some code, mainly fetching other 2 documents from the references on the document dispatched with the action. I return a forkJoin and the effect only completes the last returned observable, ignoring all past ones.

I have already tried many RxJs operators to debounce, merge, and so on but it has the same result.

The service responsible for syncing the documents

fStore.collection<ReservationDocument>('reservations', query =>
            query.where('hotel', '==', hotel.ref)
          )
          .stateChanges()
          .subscribe(actions => {
            actions.forEach(action => {
              switch (action.type) {
                case 'added':
                  console.log(action.payload);
                  store.dispatch(AddReservation({ reservation: action.payload }));
                  break;
                case 'modified':
                  store.dispatch(ModifiyReservation({ reservation: action.payload }));
                  break;
                case 'removed':
                  store.dispatch(RemoveReservation({ reservation: action.payload }));
                  break;
              }
            });
          });

And the effect

getClientAndHotel$ = createEffect(() =>
    this.actions$.pipe(
      ofType(ADD_RESERVATION),
      switchMap(
        (addReservation: {
          reservation: DocumentChange<ReservationDocument>;
        }) => {
          console.log('hello');
          return forkJoin([
            (addReservation.reservation.doc.get(
              'client'
            ) as DocumentReference).get(),
            (addReservation.reservation.doc.get(
              'hotel'
            ) as DocumentReference).get()
          ]).pipe(
            map(
              result => {
                console.log(addReservation.reservation.doc.ref.path);
                return {
                  type: UPDATE_RESERVATION,
                  client: ClientFromDocumentData(
                    result[0].data() as ClientDocument,
                    result[0].ref
                  ),
                  hotel: HotelFromDocumentData(
                    result[1].data() as HotelDocument,
                    result[1].ref
                  ),
                  reservation: addReservation.reservation
                };
              }
            )
          );
        }
      )
    )
  );

I expect for forkJoin made to complete and dispatch an action, however, no matter how many times the effect was triggered, only the last trigger will dispatch the action. I suspect it simply overwrites the subscription every time the effect gets triggered, without waiting for the previous one to complete but I have no idea how to solve this issue.

Upvotes: 1

Views: 1352

Answers (1)

timdeschryver
timdeschryver

Reputation: 15525

As the comment on this questions mentions, you should use mergeMap instead of switchMap.

switchMap will cancel a pending request, while mergeMap will handle all requests. If the order of requests matters, use concatMap.

https://rxjs-dev.firebaseapp.com/api/operators/mergeMap

https://rxjs-dev.firebaseapp.com/api/operators/switchMap

https://rxjs-dev.firebaseapp.com/api/operators/concatMap

Upvotes: 3

Related Questions