Search code examples
angularngrxngrx-store

Wait for two actions inside component ngrx store


I have 2 actions named METADATA_SUCCESS_ACTION_1 & SUCCESS_ACTION_2. How can i wait for this 2 actions to complete and then subscribe for the consolidated data.

this.actions
  .pipe(
    ofType(METADATA_SUCCESS_ACTION_1),
    take(1)
  )
  .subscribe((data1: any) => {
    console.log(data1)
  });

this.actions
  .pipe(
    ofType(SUCCESS_ACTION_2),
    take(1)
  )
  .subscribe((data2: any) => {
    console.log(data2)
  });

I want to wait for both success to happen and then work on both the data as metadata as well as success data


Solution

  • It sounds like you can make use of the forkJoin operator here (When all observables complete, emit the last emitted value from each.). From the documentation:

    Why use forkJoin?

    This operator is best used when you have a group of observables and only care about the final emitted value of each. One common use case for this is if you wish to issue multiple requests on page load (or some other event) and only want to take action when a response has been receieved for all. In this way it is similar to how you might use Promise.all.

    Be aware that if any of the inner observables supplied to forkJoin error you will lose the value of any other observables that would or have already completed if you do not catch the error correctly on the inner observable. If you are only concerned with all inner observables completing successfully you can catch the error on the outside.

    It's also worth noting that if you have an observable that emits more than one item, and you are concerned with the previous emissions forkJoin is not the correct choice. In these cases you may better off with an operator like combineLatest or zip.

    To use it, you can use the following code for your example above.

    forkJoin(
      this.actions.pipe(ofType(METADATA_SUCCESS_ACTION_1), take(1)),
      this.actions.pipe(ofType(SUCCESS_ACTION_2), take(1))
    ).subscribe(([data1, data2]) => {
      console.log(data1);
      console.log(data2);
    })