7
votes

I'm using vue-resource to fetch data from the server. A user needs to have a JWT token to get the correct data. If the token is invalid or expired, a 401 status is returned. If the user tries to access a forbidden page, a 403 is returned.

I would like to catch those errors and handle them appropriately (globally). This means, that the calls should be completely handled by the interceptor (if 401, 403).

How can I prevent the browser message "Uncaught (in promise)" and create some global error handling? I don't want to have a local error handler on every call.

I have the following interceptor:

Vue.http.interceptors.push(function (request, next) {
    request.headers.set('Authorization', Auth.getAuthHeader());

    next(function (response) {
        if (response.status === 401 || response.status === 403) {
            console.log('You are not logged in or do not have the rights to access this site.');
        }
    });
});

And the following call in the Vue methods:

methods: {
    user: function () {
        this.$http.get('http://localhost:8080/auth/user').then(function (response) {
            console.log(response);
        });
    }
}
1
Looks like you're already handling error responses in your interceptor. You don't want to hide failed responses / promises from the callers otherwise it looks like everything worked correctly. I wouldn't worry about console errors, most users won't see themPhil
@Phil, thanks for your response. Is there no side effect, when the exception is not caught in then()? I usually try to prevent browser errors (except HTTP errors).ssc-hrep3

1 Answers

2
votes

This is a bit of a dilemma, isn't it. You don't want unhandled promise rejections to get swallowed, because it means your application might not function and you won't know why, and will never get a report of the error happening.

On the other hand, it's silly to use the exact same error handling mechanism for every single .catch() statement in your application, so implementing a global error handler is definitely the way to go.

The problem is that in most cases, you will have to re-throw the error from your global error handler, because otherwise your application will think the request went through ok and will proceed to process the data, which will not exist.

But this leads to the situation where the Uncaught (in promise) error shows up, because the browser will think you didn't handle the error, whereas in reality you did, in your global error handler.

To get around this, there is now the onunhandledrejection event, and you can use that to prevent the browser from logging these errors, but then you have to make sure you process them yourself.

So what we often do is have our own error classes, and when a response error is thrown, we convert the error to one of our error classes, depending on the HTTP status code.

We also append a property to this error, something like ignoreUnhandledRejection and set it to true. Then, you can use the global handler to filter out those errors and ignore them, because you know that you have already handled them globally:

/**
 * Prevent logging already processed unhandled rejection in console
 */
window.addEventListener('unhandledrejection', event => {
  if (event.reason && event.reason.ignoreUnhandledRejection) {
    event.preventDefault();
  }
});