Restangular - How to override Error Interceptors

拈花ヽ惹草 提交于 2021-02-07 02:46:50

问题


I am using AngularJS v1.2.16 with Restangular v1.4.0, and would like to know if it's possible to override the ErrorInterceptor. If yes, how? if no, how can I work it around?

I've configured an error Interceptor like this:

RestangularProvider.setErrorInterceptor(
    function ( response ) {
        if ( response.status == 401 ) {
        dialogs.error("Unauthorized - Error 401", "You must be authenticated in order to access this content.")
            .result.then( function () {
                $location.path("/login");
            });
        }
        else {
            // Some other unknown Error.
            console.log( response );
            dialogs.error(response.statusText + " - Error " + response.status,
                "An unknown error has occurred.<br>Details: " + response.data);
        }
        // Stop the promise chain.
        return false;
    }
);

then, on another place, I make a POST call with an error handling.

function saveApple( apple ) {
    Restangular.all("apple/save").post( apple ).then(
        function ( response ) {
            console.log("Saved");
        },
        function ( response ) {
            // This is not being called.
            console.log("Error with status code", response.status);
        }
    );
}

I understand that, my "second" error handler is not being called because I'm returning false on the ErrorInterceptor.

But how can I work this around? I have lots of "REST operations" in my app, and only few of them, I want a customized behavior when something goes wrong.

So far, the only work-around I thought of, is to make the ErrorInterceptor return true, and for every other REST operations, I copy-paste the same error handler (a more general one). But this would be the last thing I would do.

Right now, is flowing like this:

  • ErrorInterceptor > End.

If possible, I want it to be like this: (Only for specific methods - not all).

  • ErrorInterceptor > Especific_ErrorHandler (if Exists) > End.

it can also be like this:

  • Especific_ErrorHandler (if Exists) > ErrorInterceptor > End.

Either way works for me.

References:

https://github.com/mgonto/restangular#seterrorinterceptor https://github.com/mgonto/restangular#how-can-i-handle-errors

Thanks in Advance!


回答1:


Here is your code:

RestangularProvider.setErrorInterceptor(
    function ( response ) {
        if ( response.status == 401 ) {
        dialogs.error("Unauthorized - Error 401", "You must be authenticated in order to access this content.")
            .result.then( function () {
                $location.path("/login");
            });
        }
        else {
            // Some other unknown Error.
            console.log( response );
            dialogs.error(response.statusText + " - Error " + response.status,
                "An unknown error has occurred.<br>Details: " + response.data);
        }
        // Stop the promise chain.
        return false;
    }
);

Why are you using an interceptor? - because you want dialogs across the board for displaying error messags.

Stopping promise chain, is it bad practice?

I don't know. Many people use error callbacks; and one use-case for error callbacks is to do some cleanup. If you kill the promise chain, how do you ensure the cleanup is done? Stopping the promise chain means your error callbacks, your catch blocks, and your finally blocks won't get called.

In the docs, the cleanup is done, you can see that deferred.reject is passed along. https://github.com/mgonto/restangular#seterrorinterceptor Maybe you misunderstood the example that was in the docs.

Possible solution #1

        // DON'T stop the promise chain.
        return true;

Possible solution #2

Don't handle unknown errors in the error interceptor.

RestangularProvider.setErrorInterceptor(
    function ( response ) {
        if ( response.status == 401 ) {
            dialogs.error("Unauthorized - Error 401", "You must be authenticated in order to access this content.")
                .result.then( function () {
                   $location.path("/login");
                });
            // Stop the promise chain.
            // all unauthorized access are handled the same.
            return false;
        }
        // Some other unknown Error.
        console.log( response );
        dialogs.error(response.statusText + " - Error " + response.status,
            "An unknown error has occurred.<br>Details: " + response.data);
        }
        // DON'T stop promise chain since error is not handled
        return true;
    }
);

Possible solution #3

call reject when you stop the promise chain.

RestangularProvider.setErrorInterceptor(
    function ( response, deferred, responseHandler ) {
        if ( response.status == 401 ) {
            dialogs.error("Unauthorized - Error 401", "You must be authenticated in order to access this content.")
                .result.then( function () {
                   // continue promise chain in this callback.
                   deferred.reject("unauthorized");
                   $location.path("/login");
                });
            // Stop the promise chain here
            // all unauthorized access are handled the same.
            return false;
        }
        // Some other unknown Error.
        console.log( response );
        dialogs.error(response.statusText + " - Error " + response.status,
            "An unknown error has occurred.<br>Details: " + response.data);
        }
        // DON'T stop promise chain since error is not handled
        return true;
    }
);



回答2:


Yes, you can create custom httpErrorHandler.

  • First you need to create a .factory, let's call it httpErrorHandler

.factory('httpErrorHandler', function ($rootScope) {
  return {
    'error': function (rejection) {
      if (rejection.status === 422) {
        $rootScope.$broadcast('422_error', rejection.data);
      } else if (rejection.status === 403) {
        $rootScope.$broadcast('403_error', rejection.data);
      } else {
        $rootScope.$broadcast('unknown', rejection.data);
      }
      return $q.reject(rejection);
    }
  };
}
  • Then register that factory to the $httpProvider interceptors

.config(function ($httpProvider) {
  $httpProvider.interceptors.push('httpErrorHandler');
});

Then just catch that $rootScope events anywhere in the application and handle them, or add some logic inside the interceptor.

I hope this will work as expected.



来源:https://stackoverflow.com/questions/28010548/restangular-how-to-override-error-interceptors

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!