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