根据先前操作的结果有条件地调度操作

时间:2020-08-03 16:12:46

标签: angular ngrx ngrx-effects

我有两个操作:验证更新。两者都可以独立调度,但是我也希望,如果调度update操作,则它首先调度validate操作,并且仅当没有验证时才继续。

如果这是同步代码,则类似于:

if (this.backendService.isValid(dataset)) {
    this.backEndService.update(dataset)
}

两个动作(以及它们相应的成功和错误动作)的定义:

export const validateDataset = createAction('[Datasets API] Validate Dataset', props<{ dataset: DataSetDto }>());
export const validateDatasetSuccess = createAction('[Datasets API] Validate Dataset Success', props<{ validationErrors: SgErrorMessage[]}>());
export const validateDatasetFail = createAction('[Datasets API] Validate Dataset Fail', props<{ error: string }>());

export const updateDataset = createAction('[Datasets API] Update Dataset', props<{ dataset: DataSetDto }>());
export const updateDatasetSuccess = createAction('[Datasets API] Update Dataset Success');
export const updateDatasetFail = createAction('[Datasets API] Update Dataset Fail', props<{ errorEntity: SgErrorEntity }>());

尝试1

如果我在监听updateDataset并尝试先调度validateDataset时有效果,那么应用.pipe()似乎永远不会被使用(可能在这里我应该使用类似{ {1}}返回布尔值,而不是也使用hasValidationErrors运算符):

filter

尝试2

我试图将其拆分为一个updateDataset$ = createEffect(() => { return this.actions$.pipe( ofType(DatasetApiActions.updateDataset), mergeMap(action => of(DatasetPageActions.validateDataset({dataset: action.dataset})).pipe( withLatestFrom(this.store.pipe(select(getValidationErrors))), filter(([action, validationErrors]) => validationErrors.length > 0), mergeMap(([action, validationErrors]) => this.datasetService.editDataSet(action.dataset).pipe( map(() => DatasetApiActions.updateDatasetSuccess()), catchError(error => of(DatasetApiActions.updateDatasetFail({error}))) )) )) ); }); 操作,该操作应依次调用saveDatasetvalidateDataset操作,并且还过滤updateDataset以仅在以下情况下运行updateDataset状态为空。我使用了validationErrors,所以动作可以顺序触发,可能是触发,但是成功/失败响应稍后出现,因此无法使用验证数据:

concatMap

也许我想的是错误的方式,应该将验证构建为异步表单验证,但是我仍然认为该问题有效。

我正在苦苦挣扎的是,我无法向saveDataset$ = createEffect(() => { return this.actions$.pipe( ofType(DatasetPageActions.saveDataset), concatMap(action => concat( of(DatasetPageActions.validateDataset({dataset: action.dataset})), of(DatasetApiActions.updateDataset({dataset: action.dataset})) )) ); }); updateDataset$ = createEffect(() => { return this.actions$.pipe( ofType(DatasetApiActions.updateDataset), withLatestFrom(this.store.pipe(select(getValidationErrors))), filter(([action, validationErrors]) => validationErrors.length == 0), tap(([action, validationErrors]) => console.log("validationErrors: " + validationErrors)) ); }, {dispatch: false}); 动作添加效果来触发validateDatasetSuccess动作,因为它可能由用户单独分派(而不仅仅是通过保存)。有什么办法可以实现这种行为?

1 个答案:

答案 0 :(得分:2)

您可以尝试以下方法:

updateDataset$ = createEffect(() => {
  return this.actions$.pipe(
    ofType(DatasetApiActions.updateDataset),

    // dispatch the `validate` action
    tap(action => this.store.dispatch(DatasetPageActions.validateDataset({dataset: action.dataset}))),

    switchMap(
      action => this.store.pipe(
        select(getValidationErrors),
        
        // we want to skip the current state
        // after all, the store is just a `BehaviorSubject`,
        // so subscribing to it will return the current state
        skip(1),
        filter(validationErrors => /* ... your condition here ... */),
        mapTo(action),
      ),
    ),
    mergeMap(
      action => this.datasetService.editDataSet(action.dataset).pipe(
        map(() => DatasetApiActions.updateDatasetSuccess()),
        catchError(error => of(DatasetApiActions.updateDatasetFail({error})))
      )
    )
  );
});
相关问题