Angularjs $ q.all

J’ai implémenté le $ q.all dans angularjs, mais je ne peux pas faire fonctionner le code. Voici mon code:

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); } 

Et voici mon contrôleur qui appelle les services:

 uploadService.uploadQuestion(questions).then(function(datas){ //the datas can not be resortingeved although the server has responded }, function(errors){ //errors can not be resortingeved also }) 

Je pense qu’il y a un problème lors de la configuration de $ q.all dans mon service.

    En javascript, il n’y a pas d’ block-level scopes function-level scopes :

    Lisez cet article sur javaScript Scoping and Hoisting .

    Voyez comment j’ai débogué votre code:

     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); }) 
    • Lorsque vous écrivez var deferred= $q.defer(); Dans une boucle for, elle est placée en haut de la fonction, cela signifie que javascript déclare cette variable sur la scope de la fonction en dehors de la for loop .
    • Avec chaque boucle, le dernier différé remplace le précédent, il n'y a pas de scope au niveau du bloc pour enregistrer une référence à cet object.
    • Lorsque des rappels asynchrones (succès / erreur) sont invoqués, ils référencent uniquement le dernier object différé et seul celui-ci est résolu, donc $ q.all n'est jamais résolu car il attend toujours d'autres objects différés.
    • Ce dont vous avez besoin est de créer une fonction anonyme pour chaque élément que vous itérez.
    • Les fonctions ayant des étendues, la référence aux objects différés est conservée dans une closure scope même après l'exécution des fonctions.
    • Comme le fait remarquer #dfsq: Il n’est pas nécessaire de construire manuellement un nouvel object différé puisque $ http renvoie lui-même une promesse.

    Solution avec angular.forEach :

    Voici un démon plongeur: 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); } 

    Mon moyen préféré est d'utiliser Array#map :

    Voici un guide de démonstration: 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 est aussi une promesse, vous pouvez le simplifier:

     return $q.all(tasks.map(function(d){ return $http.post('upload/tasks',d).then(someProcessCallback, onErrorCallback); })); 

    Le problème semble être que vous ajoutez le deffered.promise lorsque vous le deffered est la promesse que vous devez append:

    Essayez de passer à promises.push(deffered); donc vous n’ajoutez pas la promesse non emballée au tableau.

      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); }