我需要AngularJS $ HTTP服务还是什么的两个实例?(I need two instanc

2019-07-19 04:54发布

我想响应拦截器添加到我的$ http服务的错误处理的目的。 拦截器逻辑包括在必要的情况下使用$ HTTP发送错误信息到服务器, 我不想发送错误消息有关错误邮件的服务器,我的意思是,我想在发送错误信息到服务器禁用我的拦截器。

我的想法是创建一个名为“remote_log”,并把它里面的所有发送错误到服务器所需的代码服务。 当然,这服务将使用$ HTTP服务,并在其依赖列表。

然后添加为拦截到“remote_log”服务的依赖,并且需要将错误发送到服务器时使用的“remote_log”拦截器内。 存在的问题是:

拦截器必须使用$ httpProvider当$ HTTP服务仍不会被实例化/访问来定义,所以,里面的拦截器代码不能是该$ HTTP服务,因为一个“循环依赖”的错误发生的相关性。

我想,我唯一的选择就是创建我的“remote_log”,不使用$ httpProvider配置,同时创造拦截我设置的实例里面的$ HTTP服务的一个单独的实例。 我的问题是:我怎么能这样做? 任何其他的想法?

Answer 1:

1.循环依赖问题。

那么,为什么会出现这个错误吗? 下面是该过程的简要概述:

  1. $ http服务请求。
  2. $ httpProvider被要求建造它。
  3. 在施工过程中您注册拦截器,请求$ http服务不存在呢。
  4. 你得到“循环依赖”的错误。


第一个解决方案。

创建使用依赖angular.injector()。 请注意,您将创建另一个$ HTTP服务,独立于您的应用程序。

$httpProvider.interceptors.push(function($q) {
    $injector = angular.injector();
    return {
        response: function(response) {
            $injector.invoke(function($http) {
                // This is the exterior $http service!
                // This interceptor will not affect it.
            });
        }
    };
});


第二个解决方案(更好)。

注$喷油器在拦截器并使用它$ HTTP初始化后检索的依赖,就在你需要他们的时候。 这些依赖注册您的应用程序的服务,并不会重新建立!

$httpProvider.interceptors.push(function($q, $injector) {
    return {
        response: function(response) {
            $injector.invoke(function($http, someService) {
                // $http is already constructed at the time and you may
                // use it, just as any other service registered in your
                // app module and modules on which app depends on.
            });
        }
    };
});


2.拦截预防问题。

如果使用第二个解决方案,其实有两个问题:

  1. 如果您使用$ HTTP服务拦截里面,你可能最终与无限的拦截:你发送请求时,拦截捕获它发送另一个,抓住另一个,再次发送,等等。
  2. 有时候,你只想要阻止拦截的请求。

$ HTTP服务的“配置”参数只是一个对象。 您可以创建一个约定,提供自定义参数,并在你的拦截器识别它们。

例如,让我们添加“nointercept”属性来配置,并尝试复制每个用户的请求。 这是一个愚蠢的申请,但有用的例子来理解的行为:

$httpProvider.interceptors.push(function($q, $injector) {
    return {
        response: function(response) {
            if (response.config.nointercept) {
                return $q.when(response); // let it pass
            } else {
                var defer = $q.defer();
                $injector.invoke(function($http) {
                    // This modification prevents interception:
                    response.config.nointercept = true;
                    // Reuse modified config and send the same request again:
                    $http(response.config)
                        .then(function(resp) { defer.resolve(resp); },
                              function(resp) { defer.reject(resp); });
                });
                return defer.promise;
            }
        }
    };
});

具有用于拦截性能测试,可以防止控制器和服务的拦截:

app.controller('myController', function($http) {
    // The second parameter is actually 'config', see API docs.
    // This query will not be duplicated by the interceptor.
    $http.get('/foo/bar', {nointercept: true})
        .success(function(data) {
            // ...
        });

});


Answer 2:

我用什么在回答描述,但我用一个工厂的语法,因为与匿名函数没有工作,我真的不知道为什么:

(function(angular){
    angular.module('app', [])
    .config([
        '$httpProvider',
        function($httpProvider) {
                $httpProvider.interceptors.push('Interceptor');
        } 
    ])
    .factory('Interceptor', [
        '$injector',
        InterceptorFactory
    ]);

    function InterceptorFactory($injector){

        return {
            request: function(config) {             
                var ServiceWithHttp = $injector.get('ServiceWithHttp');
                // Use ServiceWithHttp
                return config;
            }
        };
    }

}(window.angular));


文章来源: I need two instances of AngularJS $http service or what?