是否可以在不完成 Observable 流的情况下在 ngrx-effects 中抛出错误?
Is it possible to throw errors inside ngrx-effects without completing the Observable stream?
有没有什么方法可以在不完成流的情况下将 throw
与 ngrx-effects 流中的错误对象一起使用?
我已经阅读了关于为什么流被抛出错误杀死的这些很好的答案:
https://github.com/ngrx/platform/issues/646
我的问题是我是否正在实施 Angular ErrorHandler
来捕获错误,如果我能够将其与 ngrx 效果一起使用。
@Effect()
loginUserEffect: Observable<loginActions.Actions> = this.actions$
.ofType(loginActions.LOGIN_USER)
.map((action: loginActions.LoginUser) => action.payload)
.mergeMap(payload => {
return this.loginService
.authenticate(payload)
.map(response => new loginActions.LoginUserSuccess(response))
.catch((error: HttpErrorResponse) =>
of(new loginActions.LoginUserFailure(error))
)
})
@Effect({ dispatch: false })
loginUserEffectSuccess$ = this.actions$
.ofType(loginActions.LOGIN_USER_SUCCESS)
.do(() => this.router.navigate(['/account-home']))
@Effect({ dispatch: false })
loginUserEffectFailure$ = this.actions$
.ofType(loginActions.LOGIN_USER_FAILURE)
.map((action: loginActions.LoginUserFailure) => {
throw action.payload // Stream completes
})
我想我可以创建一些不涉及抛出任何错误的方法来处理错误,但我想确保我需要走那条路,或者是否有办法让它们和平共存。
目前在实现 ErrorHander
的 class 中,我有这个:
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
private messagesService: MessagesService
private router: Router
constructor(
private injector: Injector, // DI workaround (
private errorLoggerService: ErrorLoggerService
) {
// DI workaround (
setTimeout(() => (this.messagesService = injector.get(MessagesService)))
setTimeout(() => (this.router = injector.get(Router)))
}
handleError(error) {
if (error instanceof HttpErrorResponse) {
this.handleServerError(error)
} else if (error instanceof ClientError) {
this.handleClientError(error)
} else {
this.handleUnexpectedError(error)
}
}
这意味着我只是抛出错误,它们是根据类型处理的
如果你想抛出一个不会被 observable 捕获的错误,而是报告给全局错误处理程序,你已经从 observable 的调用堆栈之外抛出错误。
你可以这样做:
@Effect({ dispatch: false })
loginUserEffectFailure$ = this.actions$
.ofType(loginActions.LOGIN_USER_FAILURE)
.do(action => setTimeout(() => { throw action.payload; }, 0))
})
但是,由于您的效果在 class 中已经使用了 Angular 的 DI 机制,我建议您改为注入 GlobalErrorHandler
并直接调用它。
如果没有 setTimeout
调用,我认为它也会更清晰、更容易测试。
我最终创建了一个错误操作:
@Effect()
loginUserEffectFailure$: Observable<
errorsActions.Actions
> = this.actions$
.ofType(loginActions.LOGIN_USER_FAILURE)
.map(
(action: loginActions.LoginUserFailure) =>
new errorsActions.Error(action.payload)
)
并以专用效果调用错误处理程序:
@Effect({ dispatch: false })
errorEffect$ = this.actions$
.ofType(errorsActions.ERROR)
.map((action: errorsActions.Error) =>
this.clientErrorHandler.handleError(action.payload)
)
我离开全局错误处理程序只是为了捕获和记录意外异常。
有没有什么方法可以在不完成流的情况下将 throw
与 ngrx-effects 流中的错误对象一起使用?
我已经阅读了关于为什么流被抛出错误杀死的这些很好的答案:
https://github.com/ngrx/platform/issues/646
我的问题是我是否正在实施 Angular ErrorHandler
来捕获错误,如果我能够将其与 ngrx 效果一起使用。
@Effect()
loginUserEffect: Observable<loginActions.Actions> = this.actions$
.ofType(loginActions.LOGIN_USER)
.map((action: loginActions.LoginUser) => action.payload)
.mergeMap(payload => {
return this.loginService
.authenticate(payload)
.map(response => new loginActions.LoginUserSuccess(response))
.catch((error: HttpErrorResponse) =>
of(new loginActions.LoginUserFailure(error))
)
})
@Effect({ dispatch: false })
loginUserEffectSuccess$ = this.actions$
.ofType(loginActions.LOGIN_USER_SUCCESS)
.do(() => this.router.navigate(['/account-home']))
@Effect({ dispatch: false })
loginUserEffectFailure$ = this.actions$
.ofType(loginActions.LOGIN_USER_FAILURE)
.map((action: loginActions.LoginUserFailure) => {
throw action.payload // Stream completes
})
我想我可以创建一些不涉及抛出任何错误的方法来处理错误,但我想确保我需要走那条路,或者是否有办法让它们和平共存。
目前在实现 ErrorHander
的 class 中,我有这个:
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
private messagesService: MessagesService
private router: Router
constructor(
private injector: Injector, // DI workaround (
private errorLoggerService: ErrorLoggerService
) {
// DI workaround (
setTimeout(() => (this.messagesService = injector.get(MessagesService)))
setTimeout(() => (this.router = injector.get(Router)))
}
handleError(error) {
if (error instanceof HttpErrorResponse) {
this.handleServerError(error)
} else if (error instanceof ClientError) {
this.handleClientError(error)
} else {
this.handleUnexpectedError(error)
}
}
这意味着我只是抛出错误,它们是根据类型处理的
如果你想抛出一个不会被 observable 捕获的错误,而是报告给全局错误处理程序,你已经从 observable 的调用堆栈之外抛出错误。
你可以这样做:
@Effect({ dispatch: false })
loginUserEffectFailure$ = this.actions$
.ofType(loginActions.LOGIN_USER_FAILURE)
.do(action => setTimeout(() => { throw action.payload; }, 0))
})
但是,由于您的效果在 class 中已经使用了 Angular 的 DI 机制,我建议您改为注入 GlobalErrorHandler
并直接调用它。
如果没有 setTimeout
调用,我认为它也会更清晰、更容易测试。
我最终创建了一个错误操作:
@Effect()
loginUserEffectFailure$: Observable<
errorsActions.Actions
> = this.actions$
.ofType(loginActions.LOGIN_USER_FAILURE)
.map(
(action: loginActions.LoginUserFailure) =>
new errorsActions.Error(action.payload)
)
并以专用效果调用错误处理程序:
@Effect({ dispatch: false })
errorEffect$ = this.actions$
.ofType(errorsActions.ERROR)
.map((action: errorsActions.Error) =>
this.clientErrorHandler.handleError(action.payload)
)
我离开全局错误处理程序只是为了捕获和记录意外异常。