0
votes

I have multiple effects and trying to combine it in one since there is an issue when dispatching the actions separately. I am trying to execute sequentially after checking the value returned from 1st service call. I have below three separate effects:

@Effect()
loadNqInclDResponse$ = 
  this.actions.ofType(fromActions.LOAD_NQINCLD_RESPONSE).pipe(
    switchMap(() => {
      return this.cinReuseService.WmsInCl().pipe(
        map(responseNqinclD => new 
          fromActions.LoadNqInclDResponseSuccess(responseNqinclD)),
        catchError(error => {
          const err: responseNqinclD = {
            httpStatus: "FALSE",
            message: "ERROR"
          };
          return of(new fromActions.LoadNqInclDResponseFail(err));
        })
      );  
    })
  );


@Effect()
loadCinReuseService$ = 
  this.actions.ofType(fromActions.LOAD_CIN_REUSE_SERVICE).pipe(
    switchMap(() => {
      return this.cinReuseService.cinReuseServiceCall().pipe(
        map(responseReuseService => new 
          fromActions.LoadCinReuseServiceSuccess(responseReuseService)),
        catchError(error => {
          const err: responseReuseService = {
            status: "FALSE",
            message: "ERROR"
          }
          return of(new fromActions.LoadCinReuseServiceFail(err))
        })
      );
    })
  )

@Effect()
loadCaseReuseService$ = 
  this.actions.ofType(fromActions.LOAD_CASE_REUSE_SERVICE).pipe(
    switchMap(() => {
      return this.cinReuseService.caseReuseServiceCall().pipe(
        map(responseReuseService => new fromActions.LoadCaseReuseServiceSuccess(responseReuseService)),
        catchError(error => {
          const err: responseReuseService = {
            status: "FALSE",
            message: "ERROR"
          };

          return of(new fromActions.LoadCaseReuseFail(err));
        });
      )
    });

);

I expected single effect to be as below:

@Effect()
loadNqInclDResponse1$ = 
  this.actions.ofType(fromActions.LOAD_NQINCLD_RESPONSE).pipe(
    switchMap(() => {
      return this.cinReuseService.WmsInCl().pipe(
        map(nqinclD => {        
          // new fromActions.LoadNqInclDResponseSuccess(nqinclD);
          if (nqinclD.httpStatus === '200') {
            switchMap(() => {
              return this.cinReuseService.cinReuseServiceCall().pipe(
                map(cin => new fromActions.LoadCinReuseServiceSuccess(cin)));
            }),
            switchMap(() => {
              return this.cinReuseService.caseReuseServiceCall().pipe(
                map(cse => new fromActions.LoadCaseReuseServiceSuccess(cse)));
            })
          }
        }),
        catchError(error => {
          let err: responseNqinclD = {
            httpStatus: "FALSE",
            message: "ERROR"
          };
          return of(new fromActions.LoadNqInclDResponseFail(err))
        })
      )
    })
  )
}

On a button click, I am receiving error as below when dispatching fromActions.LOAD_CIN_REUSE_SERVICE:

Error: Effect "CinReuseEffect.loadNqInclDResponse1$" dispatched an invalid action: undefined

TypeError: Actions must be objects

Service call wmsInCl() has below code for testing purpose at the moment:

WmsInCl(): Observable<responseNqinclD> {
  var body: Body;
  var response: responseNqinclD;
  console.log("1111111" + body);
   response = {
    httpStatus: "200",
    message: "SUCCESS"
  }
  console.log(response);
  return of(response);
 }
}

Thank you in advance!

1
@julianobrasil, thank you for your edit!CodeVenture

1 Answers

2
votes

Try this:

@Effect()
loadNqInclDResponse1$ = 
  this.actions.ofType(fromActions.LOAD_NQINCLD_RESPONSE).pipe(
    switchMap(() => this.cinReuseService.WmsInCl()),
    switchMap((nqinclD) => {
      if(nqinclD.httpStatus === '200') {
        return combineLatest([
          of(nqinclD),
          this.cinReuseService.cinReuseServiceCall(),
          this.cinReuseService.caseReuseServiceCall()
        ]);
      }
      const err: any = {
        httpStatus: "FALSE",
        message: "ERROR"
      };
      return of(err);
    }),
    switchMap(value => {
      if(Array.isArray(value)) {
        const [nqinclD,cin,cse] = value;
        return [
          new fromActions.LoadNqInclDResponseSuccess(nqinclD),
          new fromActions.LoadCinReuseServiceSuccess(cin),
          new fromActions.LoadCaseReuseServiceSuccess(cse),
        ];
      }

      return [
        new fromActions.LoadNqInclDResponseFail(value),
        new fromActions.LoadCinReuseServiceFail(value),
        new fromActions.LoadCaseReuseFail(value)
      ];
    }),
    catchError(error => {
      const value = {
        httpStatus: "FALSE",
        message: "ERROR"
      };
      return from([
        new fromActions.LoadNqInclDResponseFail(value),
        new fromActions.LoadCinReuseServiceFail(value),
        new fromActions.LoadCaseReuseFail(value)
      ]);
    })
  );

switchMap has a useful behavior: when it's returning an array of values, it internally converts the elements of the array to individual observables (one observable for each element of the array), like this:

of(1).pipe(switchMap((_) => [1,2,3]).subscribe(console.log);
// 1
// 2 
// 3