$ q.allをangularjsに実装しましたが、コードを機能させることができません。これが私のコードです:
UploadService.uploadQuestion = function(questions){
var promises = [];
for(var i = 0 ; i < questions.length ; i++){
var deffered = $q.defer();
var question = questions[i];
$http({
url : 'upload/question',
method: 'POST',
data : question
}).
success(function(data){
deffered.resolve(data);
}).
error(function(error){
deffered.reject();
});
promises.Push(deffered.promise);
}
return $q.all(promises);
}
そして、これが私のサービスを呼び出すコントローラーです。
uploadService.uploadQuestion(questions).then(function(datas){
//the datas can not be retrieved although the server has responded
},
function(errors){
//errors can not be retrieved also
})
私のサービスでは$ q.allの設定に問題があると思います。
Javascriptでは、block-level scopes
のみfunction-level scopes
はありません。
javaScript Scoping and Hoisting についてのこの記事を読んでください。
var deferred = $q.defer();
deferred.count = i;
console.log(deferred.count); // 0,1,2,3,4,5 --< all deferred objects
// some code
.success(function(data){
console.log(deferred.count); // 5,5,5,5,5,5 --< only the last deferred object
deferred.resolve(data);
})
var deferred= $q.defer();
を書くと、それは関数の先頭にhoistedされ、それはjavascriptがfor loop
の外側の関数スコープでこの変数を宣言することを意味します。closure scope
に保存されます。angular.forEach
による解決策:これがデモプランカーです: http://plnkr.co/edit/NGMp4ycmaCqVOmgohN53?p=preview
UploadService.uploadQuestion = function(questions){
var promises = [];
angular.forEach(questions , function(question) {
var promise = $http({
url : 'upload/question',
method: 'POST',
data : question
});
promises.Push(promise);
});
return $q.all(promises);
}
Array#map
を使うことです。これはデモプランカーです: http://plnkr.co/edit/KYeTWUyxJR4mlU77svw9?p=preview
UploadService.uploadQuestion = function(questions){
var promises = questions.map(function(question) {
return $http({
url : 'upload/question',
method: 'POST',
data : question
});
});
return $q.all(promises);
}
$ httpも約束です、あなたはそれをより簡単にすることができます:
return $q.all(tasks.map(function(d){
return $http.post('upload/tasks',d).then(someProcessCallback, onErrorCallback);
}));
deffered
がそれ自身が追加すべき約束であるとき、問題はあなたがdeffered.promise
を追加しているということのようです:
promises.Push(deffered);
に変更して、ラップされていないプロミスを配列に追加しないようにしてください。
UploadService.uploadQuestion = function(questions){
var promises = [];
for(var i = 0 ; i < questions.length ; i++){
var deffered = $q.defer();
var question = questions[i];
$http({
url : 'upload/question',
method: 'POST',
data : question
}).
success(function(data){
deffered.resolve(data);
}).
error(function(error){
deffered.reject();
});
promises.Push(deffered);
}
return $q.all(promises);
}