-
Notifications
You must be signed in to change notification settings - Fork 26.6k
Description
Which @angular/* package(s) are relevant/releated to the feature request?
common, core
Description
As an Angular developer I want a better DX and UX for handling errors that occur during change detection and event handlers by intercepting errors at the component level.
Currently I am trying to provide the ErrorHandler
service like so:
@Component({
template: `
<button (click)="explode()">Explode</button>
`,
providers: [{
provide: ErrorHandler,
useExisting: MyComponent
}]
})
export class MyComponent implements ErrorHandler {
handleError(error) {
console.error('in component', error)
}
explode() {
throw new Error("Boom!")
}
}
When I click the button I would expect the handleError
method to be called. Instead it calls the global ErrorHandler
service provided in the root module. Looking through the source code I noticed that Angular only checks for ErrorHandler
in the Module injector when an error occurs.
const injector = lView[INJECTOR]; |
Proposed solution
When Angular catches an error, it should try injecting the ErrorHandler
service from the Element injector first. If ErrorHandler
is not found, fall back to using the Module injector. This should also ideally guard against the error handler itself throwing an error by passing the thrown error to the next ErrorHandler
up the Element injector tree. Also consider using ErrorHandler
in place of re-throwing errors in core APIs such as AsyncPipe
.
Alternatives considered
- Defensive programming by writing error handling logic in many places, eg. wrapping event handlers in try catch blocks, rxjs catchError operator, etc.
- Manual change detection to catch template errors.
@Directive()
export class ErrorBoundary implements DoCheck {
ngDoCheck() {
try {
this.cdr.detectChanges()
} catch (error) {
// handle error
}
}
}