javascript - then - angularjs $http promise
Angular combina solicitudes paralelas y encadenadas con $ http.then() y $ q.all() (1)
Tengo que hacer un conjunto bastante complicado de llamadas a la API e intento hacerlo de la manera más elegante y efectiva posible. Entiendo cómo usar la API prometedora del servicio $http
para encadenar solicitudes y cómo usar el servicio $q
para realizar solicitudes en paralelo. Pero para este flujo de trabajo API específico necesito hacer ambas cosas.
Aquí hay un ejemplo del flujo API de alto nivel:
-
/dog/<dog_id>
-
/breed/<breed_id>
-
/food/<food_id>
-
-
-
/cat/<cat_id>
-
/turkey/<turkey_id>
-
/fish/<fish_id>
El primer nivel de solicitudes tiene identificadores conocidos. Sin embargo, el <breed_id>
requerido para realizar la llamada /breed
debe analizarse a partir de la respuesta /dog
, y el <food_id>
requerido para realizar la llamada /food
debe analizarse a partir de la respuesta /breed
. So /dog
, /breed
, y /food
necesitan ser encadenados. Sin embargo /cat
, /turkey
y /fish
se pueden hacer en paralelo con toda /dog
cadena /dog
.
Lo que tengo ahora (y está funcionando bien) son dos conjuntos separados de solicitudes. ¿Cómo puedo mejorar este flujo? ¿Hay alguna manera de combinar las dos pilas de una manera que resulte en una única ejecución prometedora de .then()
?
var dogId = ''472053'',
catId = ''840385'',
turkeyId = ''240987'',
fishId = ''510412'';
var myData = {};
var firstSetComplete = false,
secondSetComplete = false,
returnData = function() {
if (firstSetComplete && secondSetComplete) {
console.log("myData.dog", myData.dog);
console.log("myData.dog.breed", myData.dog.breed);
console.log("myData.dog.food", myData.dog.food);
console.log("myData.cat", myData.cat);
console.log("myData.turkey", myData.turkey);
console.log("myData.fish", myData.fish);
}
};
// first call set
$http.get(''http://example.com/dog/'' + dogId)
.then(function(response) {
myData.dog = response.data;
return $http.get(''http://example.com/breed/'' + response.data.breed_id);
})
.then(function(response) {
myData.dog.breed = response.data;
return $http.get(''http://example.com/food/'' + response.data.food_id);
})
.then(function(response) {
myData.dog.food = response.data;
firstSetComplete = true;
returnData();
});
// second call set
$q.all([
$http.get(''http://example.com/cat/'' + catId),
$http.get(''http://example.com/turkey/'' + turkeyId),
$http.get(''http://example.com/fish/'' + fishId)
])
.then(function(responses) {
myData.cat = responses[0].data;
myData.turkey = responses[1].data;
myData.fish = responses[2].data;
secondSetComplete = true;
returnData();
});
Puedes pasar en la primera cadena así:
$q.all([
$http.get(''http://example.com/cat/'' + catId),
$http.get(''http://example.com/turkey/'' + turkeyId),
$http.get(''http://example.com/fish/'' + fishId),
$http.get(''http://example.com/dog/'' + dogId)
.then(function(response) {
myData.dog = response.data;
return $http.get(''http://example.com/breed/'' + response.data.breed_id);
})
.then(function(response) {
myData.dog.breed = response.data;
return $http.get(''http://example.com/food/'' + response.data.food_id);
})
.then(function(response) {
myData.dog.food = response.data;
return myData;
})
])
.then(function(responses) {
myData.cat = responses[0].data;
myData.turkey = responses[1].data;
myData.fish = responses[2].data;
secondSetComplete = true;
returnData();
});
Esa gran cadena de promesas para perros termina devolviendo una promesa única que se resuelve cuando se llama a la última y se resuelve con el resultado de esa función final. Por lo tanto, no hay ninguna razón para no $q.all()
en su $q.all()
.