Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ngrx4 multiple actions in effects -> forkJoin not working as expected

I am trying to call multiple actions and wait for them to finish until I return the SYNC_SUCCESS action and dismiss the loading screen. But I can't get it to work.

Any suggestions what am I doing wrong here?

AppEffect:

@Effect()
syncMasterData$ = this.actions$
    .ofType<AppActions.SyncMasterdata>(AppActions.SYNC_MASTERDATA)
    .mergeMap(() => 
    {
        return Observable.forkJoin(
            Observable.of(new BarcodeConfigActions.Sync)
        ).map(() => new AppActions.SyncingSuccess);
    })

BarcodeConfigEffect

@Effect() sync$ = this.actions$
    .ofType<BarcodeConfigActions.Sync>(BarcodeConfigActions.SYNC)
    .mergeMap(() => this.apiProvider.getBarcodeConfig())
    .map((barcodeConfigs: BarcodeConfig[]) =>
    {
        let barcodeConfigState = <barcodeConfig.State>{};
        barcodeConfigState.tenant = "COOKIE";
        barcodeConfigState.barcodeConfig = barcodeConfigs;
        return new BarcodeConfigActions.SyncSuccess({ barcodeConfigs: barcodeConfigState });
    })
    .catch((error) =>
    {
        this._store.dispatch(new AppActions.UnexpectedError(error));
        return Observable.of(new BarcodeConfigActions.SyncFailed)
    })

AppAction:

export class SyncMasterdata implements Action
{
    readonly type = SYNC_MASTERDATA;
}

BarcodeConfigAction:

export class Sync implements Action
{
    readonly type = SYNC;
}

That way the barcodeconfigeffect -> sync won't be called. If I remove the forkjoin and just post the Observable.of(new BarcodeConfigActions.Sync) it works but I can't dispatch more actions.

Thanks :)

like image 529
nosTa Avatar asked Nov 27 '17 16:11

nosTa


1 Answers

If I understand the problem correctly, it seems like you want to ensure that a BarcodeConfigActions.SyncSuccess (in BarcodeConfigEffect) is dispatched before your AppActions.SyncingSuccess (in AppEffect). This is to ensure that you have received the getBarcodeConfig?

The problem with your solution is that you are forkJoining one single action, BarcodeConfigActions.Sync, and then mapping that action to an AppActions.SyncingSuccess before it is returned. This means that the BarcodeConfigActions.Sync never is emitted on the actions$ observable, which is the observable you are tapping into in your BarcodeConfigEffect.

If your syncMasterData$ effects´ only logic is to ensure that BarcodeConfigActions.SyncSuccess is called BEFORE AppActions.SyncingSuccess, perhaps just dispatch both actions forkJoined in your BarcodeConfigEffect?

@Effect() sync$ = this.actions$
.ofType<BarcodeConfigActions.Sync>(BarcodeConfigActions.SYNC)
.mergeMap(() => this.apiProvider.getBarcodeConfig())
.map((barcodeConfigs: BarcodeConfig[]) =>
{
    let barcodeConfigState = <barcodeConfig.State>{};
    barcodeConfigState.tenant = "COOKIE";
    barcodeConfigState.barcodeConfig = barcodeConfigs;
    /* NEW RETURN */
    return Observable.forkJoin(
                new AppActions.SyncingSuccess(),
                new BarcodeConfigActions.SyncSuccess({ barcodeConfigs: barcodeConfigState }));
})
.catch((error) =>
{
    this._store.dispatch(new AppActions.UnexpectedError(error));
    return Observable.of(new BarcodeConfigActions.SyncFailed)
})
like image 101
amu Avatar answered Oct 21 '22 13:10

amu