Angularjs $ q.all

我在angularjs中实现了$ q.all,但是我不能让代码工作。 这是我的代码:

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范围和提升的文章。

看看我如何debugging你的代码:

 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(); 在for循环中,它被到了函数的顶部,这意味着javascript在for loop之外的函数范围声明了这个variables。
  • 在每个循环中,最后一个被延迟的是覆盖前一个,没有块级作用域来保存对该对象的引用。
  • 当调用asynchronouscallback(成功/错误)时,它们只引用最后一个延迟对象 ,只有它被parsing,所以$ q.all永远不会被parsing,因为它仍然等待其他延迟对象。
  • 你需要的是为你迭代的每个项目创build一个匿名函数。
  • 由于函数确实具有作用域,所以即使在执行函数之后,对延迟对象的引用仍然保留在closure scope
  • 正如#dfsq所评论的那样:由于$ http本身返回一个promise,所以不需要手动构造一个新的延迟对象。

解决scheme与angular.forEach

这里是一个演示plunker: 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

这是一个演示plunker: 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.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); }