複数の$http
呼び出しを実行しようとしていますが、コードは次のようになります。
var data = ["data1","data2","data3"..."data10"];
for(var i=0;i<data.length;i++){
$http.get("http://example.com/"+data[i]).success(function(data){
console.log("success");
}).error(function(){
console.log("error");
});
}
すべての$http
呼び出しが成功したことを知ることをどのように約束できますか?いずれかが失敗した場合、何らかのアクションを実行します。
$q.all()
メソッドを使用することもできます。
だから、あなたのコードから:
var data = ["data1","data2","data3"..."data10"];
for(var i=0;i<data.length;i++){
$http.get("http://example.com/"+data[i]).success(function(data){
console.log("success");
}).error(function(){
console.log("error");
});
}
あなたができること:
var promises = [];
data.forEach(function(d) {
promises.Push($http.get('/example.com/' + d))
});
$q.all(promises).then(function(results){
results.forEach(function(data,status,headers,config){
console.log(data,status,headers,config);
})
}),
上記は基本的にリクエスト全体を実行し、すべてが完了したときの動作を設定することを意味します。
ステータスを使用すると、問題が発生したかどうかを知ることができます。また、必要に応じて、リクエストごとに異なる構成を設定することもできます(たとえば、タイムアウト)。
ドキュメントから これも A +仕様に基づく:
$q.all(successCallback, errorCallback, notifyCallback);
最初のエラーを発生させたい場合は、次のようにforループを同期させる必要があります: 進行状況バーを更新するための角度同期httpループ
var data = ["data1", "data2", "data3", "data10"];
$scope.doneLoading = false;
var promise = $q.all(null);
angular.forEach(data, function(url){
promise = promise.then(function(){
return $http.get("http://example.com/" + data[i])
.then(function (response) {
$scope.data = response.data;
})
.catch(function (response) {
$scope.error = response.status;
});
});
});
promise.then(function(){
//This is run after all of your HTTP requests are done
$scope.doneLoading = true;
});
非同期にしたい場合: バンドルする方法Angular $ http.get()呼び出し?
app.controller("AppCtrl", function ($scope, $http, $q) {
var data = ["data1", "data2", "data3", "data10"];
$q.all([
for(var i = 0;i < data.length;i++) {
$http.get("http://example.com/" + data[i])
.then(function (response) {
$scope.data= response.data;
})
.catch(function (response) {
console.error('dataerror', response.status, response.data);
break;
})
.finally(function () {
console.log("finally finished data");
});
}
]).
then(function (results) {
/* your logic here */
});
};
この記事もかなり良いです: http://chariotsolutions.com/blog/post/angularjs-corner-using-promises-q-handle-asynchronous-calls/
受け入れられた答えは大丈夫ですが、それでも少し醜いです。送信したいものの配列があります。for
ループを使用する代わりに、Array.prototype.map
を使用してみませんか?
var data = ["data1","data2","data3"..."data10"];
for(var i=0;i<data.length;i++){
$http.get("http://example.com/"+data[i]).success(function(data){
console.log("success");
}).error(function(){
console.log("error");
});
}
これは
var data = ['data1', 'data2', 'data3', ...., 'data10']
var promises = data.map(function(datum) {
return $http.get('http://example.com/' + datum)
})
var taskCompletion = $q.all(promises)
// Usually, you would want to return taskCompletion at this point,
// but for sake of example
taskCompletion.then(function(responses) {
responses.forEach(function(response) {
console.log(response)
})
})
これは高階関数を使用するため、for
ループを使用する必要はなく、見た目もはるかに簡単に見えます。それ以外の点では、投稿された他の例と同じように動作するため、これは純粋に美的な変更です。
success
とerror
の警告の一言--success
とerror
はコールバックに似ており、promiseがどのように機能するかわからないという警告です/正しく使用していません。 Promise then
とcatch
はチェーンを作成し、これまでのチェーンをカプセル化した新しいPromiseを返します。これは非常に有益です。さらに、success
とerror
($http
の呼び出しサイト以外の場所)を使用することは、Angular A +準拠のpromiseではなくHTTPpromise。
言い換えると、success
/error
を使用しないようにしてください。理由はめったになく、副作用が発生するため、ほとんどの場合、コードの臭いを示します。
あなたのコメントに関して:
私は$ q.allで非常に簡単な実験を行いました。ただし、すべての要求が成功した場合にのみトリガーされます。それが失敗した場合、何も起こりません。
これは、all
のコントラクトが、すべての約束が成功した場合はifを解決するか、少なくとも1つが失敗した場合は拒否するためです。
残念ながら、Angularの組み込みの$q
サービスにはall
しかありません。約束を拒否したい場合は、結果の約束が拒否されないようにする必要があります。これは、ほとんどの主要な約束ライブラリ(Bluebirdやkriskowalによる元のallSettled
など)に存在するQ
を使用する必要があります。 )。他の選択肢はあなた自身を転がすことです(しかし私はBluebirdを提案します)。