У меня есть два действия: проверить и обновить . Оба могут быть отправлены независимо, но мне также хотелось бы, чтобы при отправке действия обновления оно сначала отправляло действие проверки и продолжалось только в том случае, если не было проверок.
Если бы это был синхронный код, это было бы что-то вроде :
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()
(и, вероятно, здесь я должен использовать селектор типа hasValidationErrors
, возвращающий bool, вместо того, чтобы также использовать оператор filter
):
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})))
))
))
);
});
Попытка 2
Вместо этого я попытался разделить его на действие saveDataset
, которое должно вызывать оба действия validateDataset
и 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});
Может быть, я неправильно об этом думаю, и вместо этого валидацию следует строить как асинхронную c валидацию форм, но я все еще думаю, что вопрос верен.
С чем я борюсь. заключается в том, что я не могу добавить эффект к действию validateDatasetSuccess
для запуска действия updateDataset
, потому что он может быть отправлен пользователем отдельно (а не только путем сохранения). Есть ли способ добиться такого поведения?