0
votes

I am trying to return the result of a forkJoin in my effect using ngrx store, like this pseudocode demonstrates:

@Effect()
someEffect$: Observable<Action> = this.action$.pipe(
    ofType<SomeActionType>(ActionTypes.SomeActionType),
    switchMap((action: any) => 
        this.http.get<any>('some/url').pipe(
            map(someResult => {
                // this implementation is unimportant, just the gist of the flow I'm after
                const potentialResults = oneOrMany(someResult);

                if( potentialResults.length === 1 )   {
                    return new SomeAction(potentialResults[0]);
                } else {
                    observables: Observable<any> = getObservables(someResult);

                    forkJoin(observables).subscribe((result) =>
                        // this is where I get stuck    
                        return new SomeAction(result);
                    )
                }
            }
        ))
)

How can I synchronously return an action from the result of a forkJoin like this? At the moment, I'm dispatching an action directly to the store within the forkJoin block, but this is rather smelly and I would like to know how I can return this action within the forkJoin block, using another operator such as map or something along those lines. Any ideas?

2
return forkJoin(...).map(result => new SomeAction(result))martin
That doesn't work unfortunately - I get an error indicating that the effect is not returning an action; presumably because the return is within the map, and not outside of the forkJoin blockserlingpa

2 Answers

2
votes

You can't return an Observable from the map() callback. You need to use switchMap()(or another xxxMap()) to do that. You also can't subscribe to the forkJoin observable. Instead, you must map():

someEffect$: Observable<Action> = this.action$.pipe(
    ofType<SomeActionType>(ActionTypes.SomeActionType),
    switchMap(() => this.http.get<any>('some/url'),
    switchMap(someResult => {
        const potentialResults = oneOrMany(someResult);
        if (potentialResults.length === 1)   {
            return of(new SomeAction(potentialResults[0]));
        } else {
            const observables: Array<Observable<any>> = getObservables(someResult);
            return forkJoin(observables).map(result => new SomeAction(result))
        }
    })
)
1
votes

You can create a Subject and return it:

someEffect$ = createEffect(() => this.actions$.pipe(
ofType(SomeType.Save),
mergeMap(action => {
  const obsList: Observable<any>[] = createList();

  const sub: Subject<Action> = new Subject<Action>();
  forkJoin(obsList).subscribe(() => {
    sub.next(new SomeAction());
    sub.complete();
  });
  return sub;
})));