AngularJS
Promesas angulares con servicio $ q
Buscar..
Usando $ q.all para manejar múltiples promesas
Puede usar la función $q.all
para llamar a un método .then
después de que una serie de promesas se haya resuelto con éxito y recuperar los datos con los que se resolvieron.
Ejemplo:
JS:
$scope.data = []
$q.all([
$http.get("data.json"),
$http.get("more-data.json"),
]).then(function(responses) {
$scope.data = responses.map((resp) => resp.data);
});
El código anterior se ejecuta $http.get
2 veces para los datos en archivos JSON locales, cuando ambos get
método completo que resuelven sus promesas asociadas, cuando se resuelvan todas las promesas de la matriz, la .then
método comienza con las dos promesas de datos dentro de las responses
argumento de la matriz.
Luego, los datos se asignan para que se puedan mostrar en la plantilla, luego podemos mostrar
HTML:
<ul>
<li ng-repeat="d in data">
<ul>
<li ng-repeat="item in d">{{item.name}}: {{item.occupation}}</li>
</ul>
</li>
</ul>
JSON:
[{
"name": "alice",
"occupation": "manager"
}, {
"name": "bob",
"occupation": "developer"
}]
Usando el constructor $ q para crear promesas
La función constructora $q
se utiliza para crear promesas a partir de API asíncronas que utilizan devoluciones de llamada para devolver resultados.
$ q (función (resolver, rechazar) {...})
La función constructora recibe una función que se invoca con dos argumentos, resolve
y reject
que son funciones que se utilizan para resolver o rechazar la promesa.
Ejemplo 1:
function $timeout(fn, delay) {
return = $q(function(resolve, reject) {
setTimeout(function() {
try {
let r = fn();
resolve(r);
}
catch (e) {
reject(e);
}
}, delay);
};
}
El ejemplo anterior crea una promesa de la API WindowTimers.setTimeout . El marco AngularJS proporciona una versión más elaborada de esta función. Para uso, vea la referencia de la API del servicio de tiempo de espera de AngularJS $ .
Ejemplo 2:
$scope.divide = function(a, b) {
return $q(function(resolve, reject) {
if (b===0) {
return reject("Cannot devide by 0")
} else {
return resolve(a/b);
}
});
}
El código anterior que muestra una función de división promisificada, devolverá una promesa con el resultado o rechazará con una razón si el cálculo es imposible.
Luego puedes llamar y usar .then
$scope.divide(7, 2).then(function(result) {
// will return 3.5
}, function(err) {
// will not run
})
$scope.divide(2, 0).then(function(result) {
// will not run as the calculation will fail on a divide by 0
}, function(err) {
// will return the error string.
})
Operaciones diferidas usando $ q.defer
Podemos usar $q
para aplazar las operaciones hacia el futuro mientras tenemos un objeto de promesa pendiente en el presente, mediante el uso de $q.defer
Nosotros creamos una promesa que se resolverá o rechazará en el futuro.
Este método no es equivalente al uso del constructor $q
, ya que usamos $q.defer
a prometer una rutina existente que puede o no devolver (o alguna vez ha devuelto) una promesa.
Ejemplo:
var runAnimation = function(animation, duration) {
var deferred = $q.defer();
try {
...
// run some animation for a given duration
deferred.resolve("done");
} catch (err) {
// in case of error we would want to run the error hander of .then
deferred.reject(err);
}
return deferred.promise;
}
// and then
runAnimation.then(function(status) {}, function(error) {})
Asegúrese de devolver siempre un objeto
deferred.promise
o.then
o de arriesgarse a un error al invocar.then
Asegúrese de que siempre resuelve o rechaza su objeto diferido o, de lo
.then
posible que no se ejecute y corre el riesgo de una pérdida de memoria.
Usando promesas angulares con servicio $ q
$q
es un servicio incorporado que ayuda a ejecutar funciones asíncronas y a usar sus valores de retorno (o excepción) cuando finalizan el procesamiento.
$q
se integra con el mecanismo de observación del modelo $rootScope.Scope
, lo que significa una propagación más rápida de la resolución o el rechazo en sus modelos y evita repinturas innecesarias en el navegador, lo que daría como resultado una interfaz de usuario parpadeante.
En nuestro ejemplo, llamamos a nuestra fábrica getMyData
, que devuelve un objeto de promesa. Si el objeto se resolved
, devuelve un número aleatorio. Si se rejected
, devuelve un rechazo con un mensaje de error después de 2 segundos.
En fabrica angular
function getMyData($timeout, $q) {
return function() {
// simulated async function
var promise = $timeout(function() {
if(Math.round(Math.random())) {
return 'data received!'
} else {
return $q.reject('oh no an error! try again')
}
}, 2000);
return promise;
}
}
Usando promesas de guardia
angular.module('app', [])
.factory('getMyData', getMyData)
.run(function(getData) {
var promise = getData()
.then(function(string) {
console.log(string)
}, function(error) {
console.error(error)
})
.finally(function() {
console.log('Finished at:', new Date())
})
})
Para usar promesas, inyecte $q
como dependencia. Aquí inyectamos $q
en la fábrica getMyData
.
var defer = $q.defer();
Una nueva instancia de aplazado se construye llamando a $q.defer()
Un objeto diferido es simplemente un objeto que expone una promesa, así como los métodos asociados para resolverla. Se construye utilizando la función $q.deferred()
y expone tres métodos principales: resolve()
, reject()
y notify()
.
-
resolve(value)
: resuelve la promesa derivada con el valor. -
reject(reason)
- rechaza la promesa derivada con la razón. -
notify(value)
: proporciona actualizaciones sobre el estado de la ejecución de la promesa. Esto puede ser llamado varias veces antes de que la promesa sea resuelta o rechazada.
Propiedades
Se accede al objeto de promesa asociado a través de la propiedad de promesa. promise
- {Promesa} - promete el objeto asociado con este aplazado.
Se crea una nueva instancia de promesa cuando se crea una instancia diferida y se puede recuperar llamando a deferred.promise
.
El propósito del objeto de promise
es permitir que las partes interesadas tengan acceso al resultado de la tarea diferida cuando se complete.
Métodos de promesa
then(successCallback, [errorCallback], [notifyCallback])
- Independientemente de cuándo se cumplió o se rechazará la promesa, luego llama a una de las devoluciones de llamada de éxito o error de forma asincrónica tan pronto como el resultado esté disponible. Las devoluciones de llamada se llaman con un solo argumento: el resultado o la razón de rechazo. Además, la devolución de llamada de notificación se puede llamar cero o más veces para proporcionar una indicación de progreso, antes de que se resuelva o se rechace la promesa.catch(errorCallback)
- abreviatura de promise.then (null, errorCallback)finally(callback, notifyCallback)
: le permite observar el cumplimiento o rechazo de una promesa, pero hacerlo sin modificar el valor final.
Una de las características más poderosas de las promesas es la capacidad de encadenarlas. Esto permite que los datos fluyan a través de la cadena y sean manipulados y mutados en cada paso. Esto se demuestra con el siguiente ejemplo:
Ejemplo 1:
// Creates a promise that when resolved, returns 4.
function getNumbers() {
var promise = $timeout(function() {
return 4;
}, 1000);
return promise;
}
// Resolve getNumbers() and chain subsequent then() calls to decrement
// initial number from 4 to 0 and then output a string.
getNumbers()
.then(function(num) {
// 4
console.log(num);
return --num;
})
.then(function (num) {
// 3
console.log(num);
return --num;
})
.then(function (num) {
// 2
console.log(num);
return --num;
})
.then(function (num) {
// 1
console.log(num);
return --num;
})
.then(function (num) {
// 0
console.log(num);
return 'And we are done!';
})
.then(function (text) {
// "And we are done!"
console.log(text);
});
Envuelva el valor simple en una promesa usando $ q.when ()
Si todo lo que necesita es envolver el valor en una promesa, no necesita usar la sintaxis larga como aquí:
//OVERLY VERBOSE
var defer;
defer = $q.defer();
defer.resolve(['one', 'two']);
return defer.promise;
En este caso puedes escribir:
//BETTER
return $q.when(['one', 'two']);
$ q.when y su alias $ q.resolve
Envuelve un objeto que podría ser un valor o una promesa (tercera parte) que luego se puede convertir en una promesa de $ q. Esto es útil cuando se trata de un objeto que puede o no ser una promesa, o si la promesa proviene de una fuente en la que no se puede confiar.
- AngularJS $ q Referencia de la API del servicio - $ q.when
Con el lanzamiento de AngularJS v1.4.1
También puede utilizar una resolve
alias consistente con ES6
//ABSOLUTELY THE SAME AS when
return $q.resolve(['one', 'two'])
Evita el $ q diferido anti-patrón
Evita este Anti-Patrón
var myDeferred = $q.defer(); $http(config).then(function(res) { myDeferred.resolve(res); }, function(error) { myDeferred.reject(error); }); return myDeferred.promise;
No hay necesidad de fabricar una promesa con $q.defer
ya que el servicio $ http ya devuelve una promesa.
//INSTEAD
return $http(config);
Simplemente devuelva la promesa creada por el servicio $ http.