私はいくつかのangular以下のようなレガシーASP.NET .asmx Webサービスに対してajax呼び出しを行うためのファクトリーを持っています:
module.factory('productService', ["$http",
function ($http) {
return {
getSpecialProducts: function (data) {
return $http.post('/ajax/Products.asmx/GetSpecialProducs', data);
}
}
} ]);
ローカルネットワークでテストしているので、応答時間は「長すぎます」。不正な接続をシミュレートするために呼び出しを行ってから数秒で$ httpを遅延させるスマートな方法はありますか?
それとも、ファクトリメソッドへのすべての呼び出しを$ timeoutでラップする必要がありますか?
$timeout(function() {
productService.getSpecialProducs(data).success(success).error(error);
}, $scope.MOCK_ajaxDelay);
興味深い質問です!
自分で言ったように、$timeout
は遅延呼び出しの最も論理的な選択肢です。どこでも$timeout
を呼び出す代わりに、 documentation of $http
で概念的に概説されているように、$timeout
promiseに$http
promiseをラップする応答インターセプターをプッシュし、構成ブロックの1つに登録できます。これは、すべての$http
呼び出しが$timeout
遅延の影響を受けることを意味します。以下の線に沿ったもの:
$httpProvider.interceptors.Push(function($timeout) {
return {
"response": function (response) {
return $timeout(function() {
return response;
}, 2500);
}
};
});
あなたの「悪い接続をシミュレートすること」へのボーナスとして、あなたは拒否するか、ランダムに全く何もしないこともできます。 Heh heh heh。
新しいchromeデバイスエミュレーターには、ネットワーク調整機能があります。
アクセスするには:Google Chromeで、F12を押して開発者ツールを開きます。次に、左上の[デバイスモードの切り替え]アイコン([要素]メニューの左)をクリックします。
@stevuuの答えをさらに発展させる
responseInterceptors
は非推奨のようです(1.2.20時点)。interceptors
メカニズムで動作するようにコードを変更しました。
$httpProvider.interceptors.Push(function($q, $timeout) {
return {
'response': function(response) {
var defer = $q.defer();
$timeout(function() {
defer.resolve(response);
}, 2300);
return defer.promise;
}
};
});
Defer()。promiseパターンに$ qサービスを使用できます。
function someFunction(MOCK_ajaxDelay) {
var deferred = $q.defer();
$http.post('/ajax/Products.asmx/GetSpecialProducs', data).success(function(response) {
$timeout(function() {deferred.resolve({ success: true, response: response })}, MOCK_ajaxDelay);
}).error(function() {
$timeout(function() {deferred.resolve({ success: true, response: response } }, MOCK_ajaxDelay);
});
return deferred.promise;
}
someService.someFunction(500).then(function(data) {
if (data.success) {
$scope.items = data.response.d;
}
});
ただし、実際に模擬テストを行う場合は、ngMockを調べることをお勧めします。 http://docs.angularjs.org/api/ngMock 。$ httpBackend
@ stevuu's answerは正しいですが、それ以降の新しいAngularJSバージョンでは構文が変更されています。更新された構文は次のとおりです。
$httpProvider.interceptors.Push(["$q", "$timeout", function ($q, $timeout) {
function slower(response) {
var deferred = $q.defer();
$timeout(function() {
deferred.resolve(response);
}, 2000);
return deferred.promise;
}
return {
'response': slower
};
}]);
Promise apiを$ timeoutと組み合わせて使用して、これを実現できます。 $ http.post関数は、.successおよび.error(これらはhttp固有のメソッドです)を呼び出すことができるpromiseを返します。 httpリクエストが完了すると、この約束はresolvedになります。独自のプロミスを作成する場合、2秒遅らせて、httpリクエストが完了したときに解決するように指示できます。
module.factory('productService', function ($http, $q, $timeout) {
return {
getSpecialProducts: function (data) {
var defer = $q.defer();
$http.post('/ajax/Products.asmx/GetSpecialProducs', data).success(
function(data) {
// successful http request, resolve after two seconds
$timeout(function() {
defer.resolve(data);
}, 2000)
}).error(function() {
defer.reject("Http Error");
})
return defer.promise;
}
}
});
ただし、promise.then(successCallback, errorCallback)
機能を使用する必要があります。つまり、defer.resolve({})
に渡されたオブジェクトに明示的に指定しない限り、コントローラー/ディレクティブからhttpヘッダー、ステータス、構成にアクセスできなくなります。
リンク:
約束を返すサービスを使用している場合は、$ timeoutの前にreturnも配置する必要があります。
return dataService.loadSavedItem({
save_id: item.save_id,
context: item.context
}).then(function (data) {
// timeout returns a promise
return $timeout(function () {
return data;
},2000);
});
それが誰かを助けることを願っています!
質問のテストの側面に応えて、 Fiddler には、遅延をシミュレートする必要があるときに役立つ非常に便利な機能があります。
FiddlerのAutoResponder機能は、多くのhttp要求を含むJSをテストするのに非常に役立ちます。特定のhttpエラーコード、ブロック応答などで応答するように設定できます。