example await async all angularjs promise q

await - promise all angularjs example



Angularjs $ q.all (3)

$ http también es una promesa, puedes hacerlo más simple:

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

Implementé $ q.all en angularjs, pero no puedo hacer que el código funcione. Aquí está mi código:

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

Y aquí está mi controlador que llama a los servicios:

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

Creo que hay algún problema para configurar $ q.todo en mi servicio.


El problema parece ser que usted está agregando la promesa deffered.promise cuando se le deffered es la promesa que debería estar agregando:

Intenta cambiar a promises.push(deffered); por lo que no agrega la promesa sin envolver a la matriz.

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


En javascript no hay block-level scopes solo block-level scopes function-level scopes :

Lea este artículo sobre el alcance y elevación de javaScript .

Vea cómo depuré su código:

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

  • Cuando escribe var deferred= $q.defer(); dentro de un bucle for se iza a la parte superior de la función, significa que javascript declara esta variable en el alcance de la función fuera del for loop .
  • Con cada bucle, el último aplazado está anulando el anterior, no hay un alcance de nivel de bloque para guardar una referencia a ese objeto.
  • Cuando se invocan devoluciones de llamada asincrónicas (éxito / error), solo hacen referencia al último objeto diferido y solo se resuelve, por lo que $ q.all nunca se resuelve porque aún espera por otros objetos diferidos.
  • Lo que necesita es crear una función anónima para cada elemento que itere.
  • Como las funciones tienen ámbitos, la referencia a los objetos diferidos se conserva en un closure scope incluso después de que se ejecutan las funciones.
  • Como #dfsq comentó: No es necesario construir manualmente un nuevo objeto diferido ya que $ http en sí mismo devuelve una promesa.

Solución con angular.forEach :

Aquí hay un demo 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); }

Mi forma favorita es usar Array#map :

Aquí hay un demo 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); }