Спасибо за эту статью. Это был мой лучший результат в Google по запросу «обработка ошибок ngrx» 😀
Я реализовал это, как вы предложили, но мне не нравилось иметь «глобальное» состояние ошибки. Связь между действием и ошибкой была неясна, что в моем случае привело к побочным эффектам.
Мой подход сейчас следующий:
- Иметь абстрактный класс для действий, которые могут иметь ошибку/успех
import { Action } from '@ngrx/store'; type HandlerFunction<T> = T extends void ? () => void : (error: T) => void; export abstract class ResponsiveAction<SUCCESS_TYPE, ERROR_TYPE> implements Action { public abstract type: string; private successHandler: HandlerFunction<SUCCESS_TYPE>; private errorHandler: HandlerFunction<ERROR_TYPE>; public success(handler: HandlerFunction<SUCCESS_TYPE>): void { this.successHandler = handler; } public error(handler: HandlerFunction<ERROR_TYPE>): void { this.errorHandler = handler; } public handleSuccess(result: SUCCESS_TYPE): void { if (!this.successHandler) { return; } this.successHandler(result); } public handleError(error: ERROR_TYPE): void { if (!this.errorHandler) { return; } this.errorHandler(error); } }
2. Действие реализует этот класс
export class ResetPassword extends ResponsiveAction<void, string> { public readonly type: string = AuthActionTypes.ResetPassword; constructor(public payload: { email: string }) { super(); } }
3. В любом эффекте, который вызывает успех/ошибку для этого действия, вызовите методы дескриптора
@Effect() public resetPassword$: Observable<Action> = this.actions$.pipe( ofType<ResetPassword>(AuthActionTypes.ResetPassword), switchMap((action: ResetPassword) => { return from(myResetPasswordService.sendPasswordMail(action.payload.email))).pipe( map(() => { // Here action.handleSuccess(); return new ResetPasswordMailSent(); }), catchError(error => { // And here action.handleError(error.code); return of(new Error({ code: error.code })); }), ); }), );
4. Чтобы обработать ошибку/успех для этого конкретного действия, я просто назначаю обработчик там, где это необходимо, и отправляю действие.
// reset-password.page.ts [...] public resetPassword(email: string): void { const action = new ResetPassword({ email }); action.success(() => { this.success = true; }); action.error(error => { this.error = error; }); this.store.dispatch(action); } [...]
Таким образом, я не «загрязняю» свое состояние ошибками и могу реагировать на ошибку, специфичную для одного явного действия.
Пол Лессинг, мне бы очень хотелось услышать ваше мнение по этому поводу.