Las promesas tienen estado, comienzan como pendientes y pueden conformarse con:
- cumplido, lo que significa que el cálculo se completó con éxito.
- rechazado, lo que significa que el cálculo falló.
Las funciones de promesa de devolución nunca deberían arrojarse , sino que deberían devolver rechazos. Lanzar desde una función de devolución de promesa lo obligará a usar a } catch {
y a .catch
. Las personas que usan API prometidas no esperan promesas. Si no está seguro de cómo funcionan las API asíncronas en JS, consulte primero esta respuesta .
1. Carga DOM u otro evento único:
Por lo tanto, crear promesas generalmente significa especificar cuándo se liquidan, es decir, cuándo pasan a la fase cumplida o rechazada para indicar que los datos están disponibles (y se puede acceder a ellos .then
).
Con implementaciones de promesas modernas que admiten el Promise
constructor como las promesas nativas de ES6:
function load() {
return new Promise(function(resolve, reject) {
window.onload = resolve;
});
}
Luego usaría la promesa resultante de la siguiente manera:
load().then(function() {
// Do things after onload
});
Con bibliotecas que admiten diferido (usemos $ q para este ejemplo aquí, pero también usaremos jQuery más adelante):
function load() {
var d = $q.defer();
window.onload = function() { d.resolve(); };
return d.promise;
}
O con un jQuery como API, enganchando un evento que ocurre una vez:
function done() {
var d = $.Deferred();
$("#myObject").once("click",function() {
d.resolve();
});
return d.promise();
}
2. Devolución de llamada simple:
Estas API son bastante comunes ya que bueno ... las devoluciones de llamada son comunes en JS. Veamos el caso común de tener onSuccess
y onFail
:
function getUserData(userId, onLoad, onFail) { …
Con implementaciones de promesas modernas que admiten el Promise
constructor como las promesas nativas de ES6:
function getUserDataAsync(userId) {
return new Promise(function(resolve, reject) {
getUserData(userId, resolve, reject);
});
}
Con bibliotecas que admiten diferido (usemos jQuery para este ejemplo aquí, pero también hemos usado $ q arriba):
function getUserDataAsync(userId) {
var d = $.Deferred();
getUserData(userId, function(res){ d.resolve(res); }, function(err){ d.reject(err); });
return d.promise();
}
jQuery también ofrece un $.Deferred(fn)
formulario, que tiene la ventaja de permitirnos escribir una expresión que emule muy de cerca el new Promise(fn)
formulario, de la siguiente manera:
function getUserDataAsync(userId) {
return $.Deferred(function(dfrd) {
getUserData(userId, dfrd.resolve, dfrd.reject);
}).promise();
}
Nota: Aquí explotamos el hecho de que los métodos resolve
y los diferidos de jQuery reject
son "desmontables"; es decir. están vinculados a la instancia de jQuery.Deferred (). No todas las bibliotecas ofrecen esta función.
3. Devolución de llamada de estilo de nodo ("nodoback"):
Las devoluciones de llamada de estilo de nodo (devoluciones de nodo) tienen un formato particular donde las devoluciones de llamada son siempre el último argumento y su primer parámetro es un error. Primero promisifiquemos uno manualmente:
getStuff("dataParam", function(err, data) { …
A:
function getStuffAsync(param) {
return new Promise(function(resolve, reject) {
getStuff(param, function(err, data) {
if (err !== null) reject(err);
else resolve(data);
});
});
}
Con los diferidos puede hacer lo siguiente (usemos Q para este ejemplo, aunque Q ahora admite la nueva sintaxis que debería preferir ):
function getStuffAsync(param) {
var d = Q.defer();
getStuff(param, function(err, data) {
if (err !== null) d.reject(err);
else d.resolve(data);
});
return d.promise;
}
En general, no debe prometer demasiado las cosas manualmente, la mayoría de las bibliotecas de promesas que se diseñaron teniendo en cuenta el Nodo, así como las promesas nativas en el Nodo 8+, tienen un método incorporado para promulgar las devoluciones de nodo. Por ejemplo
var getStuffAsync = Promise.promisify(getStuff); // Bluebird
var getStuffAsync = Q.denodeify(getStuff); // Q
var getStuffAsync = util.promisify(getStuff); // Native promises, node only
4. Una biblioteca completa con devoluciones de llamada de estilo de nodo:
No hay una regla de oro aquí, los prometes uno por uno. Sin embargo, algunas implementaciones prometedoras le permiten hacer esto de forma masiva, por ejemplo, en Bluebird, convertir una API de retorno de nodo en una API de promesa es tan simple como:
Promise.promisifyAll(API);
O con promesas nativas en Node :
const { promisify } = require('util');
const promiseAPI = Object.entries(API).map(([key, v]) => ({key, fn: promisify(v)}))
.reduce((o, p) => Object.assign(o, {[p.key]: p.fn}), {});
Notas:
- Por supuesto, cuando está en un
.then
controlador no necesita prometer cosas. Devolver una promesa de un .then
manejador se resolverá o rechazará con el valor de esa promesa. Lanzar desde un .then
controlador también es una buena práctica y rechazará la promesa: esta es la famosa promesa de seguridad de lanzamiento.
- En un
onload
caso real , debe usar en addEventListener
lugar de onX
.