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.
});
}
};
});
2番目の解決策(より良い)。
インターセプターに $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.傍受防止の問題。
2 番目の解決策を使用する場合、実際には 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) {
// ...
});
});