1。循环依赖问题。
那么,为什么会出现错误?以下是该过程的简要概述:
- 请求了$http服务。
- $httpProvider 被要求构建它。
- 在构建过程中,您注册了拦截器,该拦截器请求的 $http 服务尚不存在。
- 您收到“循环依赖”错误。
第一个解决方案。
使用 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.
});
}
};
});
第二个解决方案(更好)。
在您的拦截器中注入 $injector 并在 $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。拦截预防问题。
如果使用第二种方案,其实有两个问题:
- 如果你在你的内部使用 $http 服务
拦截器,你最终可能会被无限拦截:你发送
请求,拦截器捕获它,发送另一个,捕获另一个,
再次发送,依此类推。
- 有时您只想防止请求被拦截。
$http 服务的 'config' 参数只是一个对象。您可以创建一个约定,提供自定义参数并在您的拦截器中识别它们。
例如,让我们在配置中添加“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) {
// ...
});
});