AngularJS httpInterceptors和toastr

时间:2015-08-11 15:48:22

标签: angularjs

我现在有一个处理我的$ http错误的拦截器。看起来有点像这样:

.factory('RequestsErrorHandler', ['$q', '$injector', '$rootScope', 'ErrorService', function ($q, $injector, $rootScope, service) {
    var specificallyHandled = function (specificallyHandledBlock) {
        specificallyHandleInProgress = true;

        try {
            return specificallyHandledBlock();
        } finally {
            specificallyHandleInProgress = false;
        }
    };

    var responseError = function (rejection) {

        // Create the variable for handling errors
        var shouldHandle = (rejection && rejection.config && rejection.config.headers && rejection.config.headers['handle-generic-errors']);

        // If we should handle an error
        if (shouldHandle) {

            // Get our error
            var error = service.process(rejection);

            // Assign our error to the rootScope
            $rootScope.serverError = error;

            // Redirect to our error screen
            $injector.get('$state').transitionTo('error');
        }

        // Fallback, reject the promise
        return $q.reject(rejection);
    };

    return {
        specificallyHandled: specificallyHandled,
        responseError: responseError
    };
}])

我在我的app配置中设置了这个:

.config(['$httpProvider', '$provide', function ($httpProvider, $provide) {
    $httpProvider.interceptors.push('RequestsErrorHandler'); // Add our interceptor to handle http requests

    // Decorate $http to add a special header by default
    function addHeaderToConfig(config) {
        config = config || {};
        config.headers = config.headers || {};

        // Add the header unless user asked to handle errors himself
        if (!specificallyHandleInProgress) {
            config.headers['handle-generic-errors'] = true;
        }

        return config;
    }

    // The rest here is mostly boilerplate needed to decorate $http safely
    $provide.decorator('$http', ['$delegate', function ($delegate) {
        function decorateRegularCall(method) {
            return function (url, config) {
                return $delegate[method](url, addHeaderToConfig(config));
            };
        }

        function decorateDataCall(method) {
            return function (url, data, config) {
                return $delegate[method](url, data, addHeaderToConfig(config));
            };
        }

        function copyNotOverriddenAttributes(newHttp) {
            for (var attr in $delegate) {
                if (!newHttp.hasOwnProperty(attr)) {
                    if (typeof ($delegate[attr]) === 'function') {
                        newHttp[attr] = function () {
                            return $delegate.apply($delegate, arguments);
                        };
                    } else {
                        newHttp[attr] = $delegate[attr];
                    }
                }
            }
        }

        var newHttp = function (config) {
            return $delegate(addHeaderToConfig(config));
        };

        newHttp.get = decorateRegularCall('get');
        newHttp.delete = decorateRegularCall('delete');
        newHttp.head = decorateRegularCall('head');
        newHttp.jsonp = decorateRegularCall('jsonp');
        newHttp.post = decorateDataCall('post');
        newHttp.put = decorateDataCall('put');

        copyNotOverriddenAttributes(newHttp);

        return newHttp;
    }]);
}])

现在,这工作正常。但是对于每个未处理的错误,它开始变得烦人。所以相反我认为我可能会把它作为一个toastr错误,所以我改变了我的服务:

.factory('RequestsErrorHandler', ['ErrorService', 'toastr', function (service, toastr) {
    var specificallyHandled = function (specificallyHandledBlock) {
        specificallyHandleInProgress = true;

        try {
            return specificallyHandledBlock();
        } finally {
            specificallyHandleInProgress = false;
        }
    };

    var responseError = function (rejection) {

        // Create the variable for handling errors
        var shouldHandle = (rejection && rejection.config && rejection.config.headers && rejection.config.headers['handle-generic-errors']);

        // If we should handle an error
        if (shouldHandle) {

            // Get our error
            var error = service.process(rejection);

            // Display the error
            toastr.error(error);
        }

        // Fallback, reject the promise
        return $q.reject(rejection);
    };

    return {
        specificallyHandled: specificallyHandled,
        responseError: responseError
    };
}])

但是当我尝试运行时,我收到一条错误说明:

  
    

发现循环依赖:$ http< - $ templateRequest< - $$ animateQueue< - $ animate< - toastr< - RequestsErrorHandler< - $ http< - $ templateFactory< - $ view< - $ state

  

我不确定如何解决这个问题,还有其他人知道吗?

1 个答案:

答案 0 :(得分:4)

有两种简单的方法可以解决这种循环依赖问题

  1. 通过使用事件来解耦服务:当在拦截器中检测到错误时,在根范围上广播事件(带有错误信息)。在toastr服务中(或在使用toastr的服务中),在根范围上侦听这些事件并显示它们。
  2. 而不是在拦截器中注入toastr,注入$ injector服务。当您需要toastr实例时,请致电$injector.get('toastr')