Vue.js — Global errors handling
Errors are the most popular things that would happen with any programmer. From large and scalable to simple application — all of them have potentially errors. You should to spend a lot of time to find and fix them. If you have a project dure long time you couldn’t intercept all errors. Next we will write simple and useful global errors handler and each developer could use it individual.
Theory
Need to create service that will be active since before Vue startup to closing of page. So need to use Singleton pattern for this service. It means only one instance of service will be available in application. Also need to use this pattern because application shouldn’t have any collisions while errors will process.
Errors processing — storing them in separated service for developers. Need to write interface which could stream errors to this service. As separated service would be sentry.io or another own server. Our task is just stream errors to server without losts.
Create application
As application template choose my own based on typescript + decorators components(link to template).
- Also you could to translate code into JavaScript ES6. It will work like in TypeScript
Coding
Create service
Let’s start from JavaScript-class based on singleton pattern. We will use one of the most popular method.
export class ErrorsService {
private static shared = new ErrorsService();
static get instance() {
return this.shared;
} constructor() {
}
}
Next need to write some stream for errors. For this functional I will use rx.js. You could use something different. It doesn't matters.
export class ErrorsService {
private static shared = new ErrorsService();
public errors$: Observable<Error>;
private errorsStream$ = new ReplaySubject<Error>(1); public static get instance() {
return this.shared;
} constructor() {
this.errors$ = this.errorsStream$.asObservable();
}
}
- Note: It’s very important to separate Observer and Observable because need protect any pushs to stream.
Next need write errors handler function which will push them to stream.
public onError(error: Error) {
this.errorsStream$.next(error);
}private initHandler() {
const scope = this;
window.onerror = (message: Event | string, url?: string, lineNo?: number, columnNo?: number, error?: Error) => {
if (error) scope.onError(error);
};
}
Now We have the two functions. First function “On Error” get error and push it to stream. Also this function will contain some rules for errors(It will written next). Second function “initHandler” add “error” window event listener which will intercept almost all errors in application.
- Note: window.onerror doesn't intercepts all errors. So sometimes need to push errors to service manually.
Handle Vue.js errors
Window errors handling doesn’t provide Vue.js errors(e.g. errors when component mounts) handling. So need to tell Vue.js — how to process errors. Open main.ts file and write next:
Vue.config.errorHandler = (error) => ErrorsService.getInstance.onError(error);
Handle http errors
Part of http errors doesn't mean something bad. For example 400 status which usually uses in POST methods means wrong filled data and service shouldn’t send them to server. So need to skip all http error-statuses in handler. It’s all statuses between 400 and 404(proof). In my opinion another 4xx statuses should be as error. E.g. axios handling:
onError(error: Error) {
const response = (error as AxiosError).response;
if (response && response.status >= 400 && response.status < 405) {
return false;
}
this.errorsStream$.next(error);
}
Send errors to server
This part is individual for developer because You could upload it whenever You want. I prefer upload them each time when error will pushed to stream.
// App.ts...mounted() {
ErrorsService.errors$
.pipe(flatMap(error => httpClient.post('/somepath', error)))
.subscribe();
}...
Conclusion
We have the service which could handle manual, window and Vue.js errors, filter them and send to server. Thoughts about increase performance and usability: use Worker for separeted stream on OS-level, use ServiceWorker for handling push notification errors.
Thank you for reading!
Our telegram channel: https://t.me/frontend_html_css_js