Buscar..
Sintaxis
- nueva Promesa (/ * función ejecutora: * / función (resolver, rechazar) {})
- promesa.then (onFulfilled [, onRejected])
- promise.catch (onRejected)
- Promise.resolve (resolución)
- Promise.reject (razón)
- Promise.all (iterable)
- Promesa.race (iterable)
Observaciones
Las promesas forman parte de la especificación ECMAScript 2015 y el soporte del navegador es limitado, ya que el 88% de los navegadores en todo el mundo lo admiten a partir de julio de 2017. La siguiente tabla ofrece una descripción general de las versiones más antiguas del navegador que brindan soporte para las promesas.
Cromo | Borde | Firefox | explorador de Internet | Ópera | mini Opera | Safari | iOS Safari |
---|---|---|---|---|---|---|---|
32 | 12 | 27 | X | 19 | X | 7.1 | 8 |
En entornos que no los admiten, Promise
se puede rellenar con polietileno. Las bibliotecas de terceros también pueden proporcionar funcionalidades extendidas, como la "promisificación" automatizada de las funciones de devolución de llamada o métodos adicionales como el progress
también conocido como notify
.
El sitio web Promises / A + standard proporciona una lista de implementaciones compatibles con 1.0 y 1.1 . Las devoluciones de llamada de promesa basadas en el estándar A + siempre se ejecutan de forma asincrónica como microtasks en el bucle de eventos .
Encadenamiento de promesa
La then
método de una promesa devuelve una nueva promesa.
const promise = new Promise(resolve => setTimeout(resolve, 5000));
promise
// 5 seconds later
.then(() => 2)
// returning a value from a then callback will cause
// the new promise to resolve with this value
.then(value => { /* value === 2 */ });
Devolver una Promise
de una devolución de llamada en then
agregará a la cadena de promesa.
function wait(millis) {
return new Promise(resolve => setTimeout(resolve, millis));
}
const p = wait(5000).then(() => wait(4000)).then(() => wait(1000));
p.then(() => { /* 10 seconds have passed */ });
Una catch
permite que una promesa rechazada se recupere, de manera similar a cómo funciona la catch
en una declaración de try
/ catch
. Cualquier encadenado then
una catch
ejecutará su controlador de resolución utilizando el valor resuelto de la catch
.
const p = new Promise(resolve => {throw 'oh no'});
p.catch(() => 'oh yes').then(console.log.bind(console)); // outputs "oh yes"
Si no hay catch
o reject
en el medio de la cadena, una catch
al final capturará cualquier rechazo en la cadena:
p.catch(() => Promise.reject('oh yes'))
.then(console.log.bind(console)) // won't be called
.catch(console.error.bind(console)); // outputs "oh yes"
En ciertas ocasiones, es posible que desee "ramificar" la ejecución de las funciones. Puede hacerlo devolviendo diferentes promesas desde una función dependiendo de la condición. Más adelante en el código, puede combinar todas estas ramas en una para llamar a otras funciones y / o para manejar todos los errores en un solo lugar.
promise
.then(result => {
if (result.condition) {
return handlerFn1()
.then(handlerFn2);
} else if (result.condition2) {
return handlerFn3()
.then(handlerFn4);
} else {
throw new Error("Invalid result");
}
})
.then(handlerFn5)
.catch(err => {
console.error(err);
});
Así, el orden de ejecución de las funciones se ve así:
promise --> handlerFn1 -> handlerFn2 --> handlerFn5 ~~> .catch()
| ^
V |
-> handlerFn3 -> handlerFn4 -^
La catch
única obtendrá el error en cualquier rama que pueda ocurrir.
Introducción
Un objeto Promise
representa una operación que ha producido o que eventualmente producirá un valor. Las promesas proporcionan una forma sólida de envolver el resultado (posiblemente pendiente) de un trabajo asíncrono, mitigando el problema de las devoluciones de llamadas profundamente anidadas (conocidas como " infierno de devolución de llamada ").
Estados y flujo de control.
Una promesa puede estar en uno de tres estados:
- pendiente : la operación subyacente aún no se ha completado, y la promesa está pendiente de cumplimiento.
- cumplido : la operación ha finalizado y la promesa se cumple con un valor . Esto es análogo a devolver un valor desde una función síncrona.
- rechazado : se ha producido un error durante la operación y la promesa se rechaza con un motivo . Esto es análogo a lanzar un error en una función síncrona.
Se dice que una promesa se liquida (o se resuelve ) cuando se cumple o se rechaza. Una vez que se establece una promesa, se vuelve inmutable y su estado no puede cambiar. Los métodos then
y catch
de una promesa se pueden usar para adjuntar devoluciones de llamada que se ejecutan cuando se resuelve. Estas devoluciones de llamada se invocan con el valor de cumplimiento y el motivo de rechazo, respectivamente.
Ejemplo
const promise = new Promise((resolve, reject) => {
// Perform some work (possibly asynchronous)
// ...
if (/* Work has successfully finished and produced "value" */) {
resolve(value);
} else {
// Something went wrong because of "reason"
// The reason is traditionally an Error object, although
// this is not required or enforced.
let reason = new Error(message);
reject(reason);
// Throwing an error also rejects the promise.
throw reason;
}
});
Los métodos then
y catch
se pueden usar para adjuntar devoluciones de llamadas de cumplimiento y rechazo:
promise.then(value => {
// Work has completed successfully,
// promise has been fulfilled with "value"
}).catch(reason => {
// Something went wrong,
// promise has been rejected with "reason"
});
Nota: Llamar a promise.then(...)
y promise.catch(...)
en la misma promesa puede dar como resultado una Uncaught exception in Promise
si se produce un error, ya sea al ejecutar la promesa o dentro de una de las devoluciones de llamada, por lo que la forma preferida sería adjuntar la siguiente oyente con la promesa de regresar por el anterior then
/ catch
.
Alternativamente, ambas devoluciones de llamada se pueden adjuntar en una sola llamada para then
:
promise.then(onFulfilled, onRejected);
Adjuntar devoluciones de llamada a una promesa que ya se ha resuelto las colocará inmediatamente en la cola de microtask , y se invocarán "tan pronto como sea posible" (es decir, inmediatamente después de la secuencia de comandos en ejecución). No es necesario verificar el estado de la promesa antes de adjuntar devoluciones de llamada, a diferencia de muchas otras implementaciones que emiten eventos.
Función de retardo llamada
El método setTimeout()
llama a una función o evalúa una expresión después de un número específico de milisegundos. También es una forma trivial de lograr una operación asíncrona.
En este ejemplo, llamar a la función de wait
resuelve la promesa después del tiempo especificado como primer argumento:
function wait(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
wait(5000).then(() => {
console.log('5 seconds have passed...');
});
Esperando múltiples promesas concurrentes
El método estático Promise.all()
acepta una promesa (por ejemplo, una Array
) de promesas y devuelve una nueva promesa, que se resuelve cuando todas las promesas en la iterable se han resuelto, o se rechazan si al menos una de las promesas en la iterable se ha rechazado.
// wait "millis" ms, then resolve with "value"
function resolve(value, milliseconds) {
return new Promise(resolve => setTimeout(() => resolve(value), milliseconds));
}
// wait "millis" ms, then reject with "reason"
function reject(reason, milliseconds) {
return new Promise((_, reject) => setTimeout(() => reject(reason), milliseconds));
}
Promise.all([
resolve(1, 5000),
resolve(2, 6000),
resolve(3, 7000)
]).then(values => console.log(values)); // outputs "[1, 2, 3]" after 7 seconds.
Promise.all([
resolve(1, 5000),
reject('Error!', 6000),
resolve(2, 7000)
]).then(values => console.log(values)) // does not output anything
.catch(reason => console.log(reason)); // outputs "Error!" after 6 seconds.
Los valores no prometedores en lo iterable son "promisificados" .
Promise.all([
resolve(1, 5000),
resolve(2, 6000),
{ hello: 3 }
])
.then(values => console.log(values)); // outputs "[1, 2, { hello: 3 }]" after 6 seconds
La tarea de destrucción puede ayudar a recuperar resultados de múltiples promesas.
Promise.all([
resolve(1, 5000),
resolve(2, 6000),
resolve(3, 7000)
])
.then(([result1, result2, result3]) => {
console.log(result1);
console.log(result2);
console.log(result3);
});
Esperando la primera de las múltiples promesas concurrentes.
El método estático Promise.race()
acepta una Promesa iterable y devuelve una Promesa nueva que se resuelve o rechaza tan pronto como la primera de las promesas en el iterable se resuelve o rechaza.
// wait "milliseconds" milliseconds, then resolve with "value"
function resolve(value, milliseconds) {
return new Promise(resolve => setTimeout(() => resolve(value), milliseconds));
}
// wait "milliseconds" milliseconds, then reject with "reason"
function reject(reason, milliseconds) {
return new Promise((_, reject) => setTimeout(() => reject(reason), milliseconds));
}
Promise.race([
resolve(1, 5000),
resolve(2, 3000),
resolve(3, 1000)
])
.then(value => console.log(value)); // outputs "3" after 1 second.
Promise.race([
reject(new Error('bad things!'), 1000),
resolve(2, 2000)
])
.then(value => console.log(value)) // does not output anything
.catch(error => console.log(error.message)); // outputs "bad things!" after 1 second
Valores "prometedores"
El método estático Promise.resolve
se puede usar para envolver valores en promesas.
let resolved = Promise.resolve(2);
resolved.then(value => {
// immediately invoked
// value === 2
});
Si el value
ya es una promesa, Promise.resolve
simplemente la Promise.resolve
.
let one = new Promise(resolve => setTimeout(() => resolve(2), 1000));
let two = Promise.resolve(one);
two.then(value => {
// 1 second has passed
// value === 2
});
De hecho, value
puede ser cualquier "thenable" (objeto que define una then
método que funciona suficientemente como una promesa spec compatible). Esto permite que Promise.resolve
convierta los objetos de terceros no confiables en Promesas de terceros confiables.
let resolved = Promise.resolve({
then(onResolved) {
onResolved(2);
}
});
resolved.then(value => {
// immediately invoked
// value === 2
});
El método estático Promise.reject
devuelve una promesa que se rechaza inmediatamente con el reason
dado.
let rejected = Promise.reject("Oops!");
rejected.catch(reason => {
// immediately invoked
// reason === "Oops!"
});
Funciones "prometedoras" con devoluciones de llamada
Dada una función que acepta una devolución de llamada de estilo de nodo,
fooFn(options, function callback(err, result) { ... });
puedes promisificarlo (convertirlo en una función basada en la promesa) de esta manera:
function promiseFooFn(options) {
return new Promise((resolve, reject) =>
fooFn(options, (err, result) =>
// If there's an error, reject; otherwise resolve
err ? reject(err) : resolve(result)
)
);
}
Esta función se puede utilizar de la siguiente manera:
promiseFooFn(options).then(result => {
// success!
}).catch(err => {
// error!
});
De una manera más genérica, aquí se muestra cómo prometer cualquier función dada de estilo de devolución de llamada:
function promisify(func) {
return function(...args) {
return new Promise((resolve, reject) => {
func(...args, (err, result) => err ? reject(err) : resolve(result));
});
}
}
Esto se puede utilizar de esta manera:
const fs = require('fs');
const promisedStat = promisify(fs.stat.bind(fs));
promisedStat('/foo/bar')
.then(stat => console.log('STATE', stat))
.catch(err => console.log('ERROR', err));
Manejo de errores
Los errores generados por las promesas se manejan mediante el segundo parámetro ( reject
) que se pasa a then
o por el controlador que se pasa a catch
:
throwErrorAsync()
.then(null, error => { /* handle error here */ });
// or
throwErrorAsync()
.catch(error => { /* handle error here */ });
Encadenamiento
Si tiene una cadena de promesa, un error hará que se resolve
manejadores de resolve
:
throwErrorAsync()
.then(() => { /* never called */ })
.catch(error => { /* handle error here */ });
Lo mismo se aplica a sus funciones de then
. Si un controlador de resolve
lanza una excepción, se invocará el siguiente controlador de reject
:
doSomethingAsync()
.then(result => { throwErrorSync(); })
.then(() => { /* never called */ })
.catch(error => { /* handle error from throwErrorSync() */ });
Un controlador de errores devuelve una nueva promesa, permitiéndole continuar una cadena de promesa. La promesa devuelta por el controlador de errores se resuelve con el valor devuelto por el controlador:
throwErrorAsync()
.catch(error => { /* handle error here */; return result; })
.then(result => { /* handle result here */ });
Puedes dejar que un error caiga en cascada en una cadena de promesa volviendo a lanzar el error:
throwErrorAsync()
.catch(error => {
/* handle error from throwErrorAsync() */
throw error;
})
.then(() => { /* will not be called if there's an error */ })
.catch(error => { /* will get called with the same error */ });
Es posible lanzar una excepción que no esté manejada por la promesa envolviendo la declaración de throw
dentro de una setTimeout
llamada setTimeout
:
new Promise((resolve, reject) => {
setTimeout(() => { throw new Error(); });
});
Esto funciona porque las promesas no pueden manejar las excepciones lanzadas de forma asíncrona.
Rechazos no manejados
Un error se ignorará silenciosamente si una promesa no tiene un bloque catch
o un controlador de reject
:
throwErrorAsync()
.then(() => { /* will not be called */ });
// error silently ignored
Para evitar esto, siempre use un bloque catch
:
throwErrorAsync()
.then(() => { /* will not be called */ })
.catch(error => { /* handle error*/ });
// or
throwErrorAsync()
.then(() => { /* will not be called */ }, error => { /* handle error*/ });
Alternativamente, suscríbase al evento unhandledrejection
para capturar cualquier promesa rechazada no manejada:
window.addEventListener('unhandledrejection', event => {});
Algunas promesas pueden manejar su rechazo más tarde que su tiempo de creación. El evento manejado por el rejectionhandled
se desencadena cuando se maneja tal promesa:
window.addEventListener('unhandledrejection', event => console.log('unhandled'));
window.addEventListener('rejectionhandled', event => console.log('handled'));
var p = Promise.reject('test');
setTimeout(() => p.catch(console.log), 1000);
// Will print 'unhandled', and after one second 'test' and 'handled'
El argumento del event
contiene información sobre el rechazo. event.reason
es el objeto de error y event.promise
es el objeto de promesa que causó el evento.
En nodejs los rejectionhandled
y unhandledrejection
eventos se llaman rejectionHandled
y unhandledRejection
el process
, respectivamente, y tienen una firma diferente:
process.on('rejectionHandled', (reason, promise) => {});
process.on('unhandledRejection', (reason, promise) => {});
El argumento de la reason
es el objeto de error y el argumento de promise
es una referencia al objeto de promesa que causó que el evento se activara.
El uso de estos eventos de rejectionhandled
y rejectionhandled
unhandledrejection
debe considerarse solo para fines de depuración. Típicamente, todas las promesas deben manejar sus rechazos.
Nota: Actualmente, solo Chrome 49+ y Node.js son compatibles con los eventos de rejectionhandled
y rejectionhandled
unhandledrejection
manejados.
Advertencias
Encadenamiento con fulfill
y reject
La función then(fulfill, reject)
(con ambos parámetros no null
) tiene un comportamiento único y complejo, y no debe usarse a menos que sepa exactamente cómo funciona.
La función funciona como se espera si se otorga un null
para una de las entradas:
// the following calls are equivalent
promise.then(fulfill, null)
promise.then(fulfill)
// the following calls are also equivalent
promise.then(null, reject)
promise.catch(reject)
Sin embargo, adopta un comportamiento único cuando se dan ambas entradas:
// the following calls are not equivalent!
promise.then(fulfill, reject)
promise.then(fulfill).catch(reject)
// the following calls are not equivalent!
promise.then(fulfill, reject)
promise.catch(reject).then(fulfill)
La función then(fulfill, reject)
parece que es un atajo para then(fulfill).catch(reject)
, pero no lo es, y causará problemas si se usa indistintamente. Uno de estos problemas es que el controlador de reject
no controla los errores del controlador de fulfill
. Esto es lo que sucederá:
Promise.resolve() // previous promise is fulfilled
.then(() => { throw new Error(); }, // error in the fulfill handler
error => { /* this is not called! */ });
El código anterior dará lugar a una promesa rechazada porque el error se propaga. Compárelo con el siguiente código, que resulta en una promesa cumplida:
Promise.resolve() // previous promise is fulfilled
.then(() => { throw new Error(); }) // error in the fulfill handler
.catch(error => { /* handle error */ });
Existe un problema similar cuando se usa then(fulfill, reject)
indistintamente con catch(reject).then(fulfill)
, excepto con promesas cumplidas en lugar de promesas rechazadas.
Lanzamiento sincrónico de la función que debería devolver una promesa.
Imagina una función como esta:
function foo(arg) {
if (arg === 'unexepectedValue') {
throw new Error('UnexpectedValue')
}
return new Promise(resolve =>
setTimeout(() => resolve(arg), 1000)
)
}
Si dicha función se usa en medio de una cadena de promesa, entonces aparentemente no hay problema:
makeSomethingAsync().
.then(() => foo('unexpectedValue'))
.catch(err => console.log(err)) // <-- Error: UnexpectedValue will be caught here
Sin embargo, si la misma función se llama fuera de una cadena de promesa, entonces el error no será manejado por ella y se lanzará a la aplicación:
foo('unexpectedValue') // <-- error will be thrown, so the application will crash
.then(makeSomethingAsync) // <-- will not run
.catch(err => console.log(err)) // <-- will not catch
Hay 2 soluciones posibles:
Devuelve una promesa rechazada con el error.
En lugar de lanzar, haz lo siguiente:
function foo(arg) {
if (arg === 'unexepectedValue') {
return Promise.reject(new Error('UnexpectedValue'))
}
return new Promise(resolve =>
setTimeout(() => resolve(arg), 1000)
)
}
Envuelve tu función en una cadena de promesa
Su declaración de throw
se capturará correctamente cuando ya esté dentro de una cadena de promesa:
function foo(arg) {
return Promise.resolve()
.then(() => {
if (arg === 'unexepectedValue') {
throw new Error('UnexpectedValue')
}
return new Promise(resolve =>
setTimeout(() => resolve(arg), 1000)
)
})
}
Conciliación de operaciones síncronas y asíncronas.
En algunos casos, es posible que desee ajustar una operación síncrona dentro de una promesa para evitar la repetición en las ramas de código. Tomemos este ejemplo:
if (result) { // if we already have a result
processResult(result); // process it
} else {
fetchResult().then(processResult);
}
Las ramas síncronas y asíncronas del código anterior se pueden reconciliar envolviendo de forma redundante la operación síncrona dentro de una promesa:
var fetch = result
? Promise.resolve(result)
: fetchResult();
fetch.then(processResult);
Cuando se almacena en caché el resultado de una llamada asíncrona, es preferible almacenar la promesa en lugar del resultado en sí. Esto garantiza que solo se requiere una operación asíncrona para resolver múltiples solicitudes paralelas.
Se debe tener cuidado de invalidar los valores almacenados en caché cuando se encuentran condiciones de error.
// A resource that is not expected to change frequently
var planets = 'http://swapi.co/api/planets/';
// The cached promise, or null
var cachedPromise;
function fetchResult() {
if (!cachedPromise) {
cachedPromise = fetch(planets)
.catch(function (e) {
// Invalidate the current result to retry on the next fetch
cachedPromise = null;
// re-raise the error to propagate it to callers
throw e;
});
}
return cachedPromise;
}
Reducir una matriz a promesas encadenadas
Este patrón de diseño es útil para generar una secuencia de acciones asíncronas a partir de una lista de elementos.
Hay dos variantes:
- la reducción "entonces", que construye una cadena que continúa mientras la cadena experimente el éxito.
- la reducción de "captura", que construye una cadena que continúa mientras la cadena experimenta un error.
La reducción "entonces"
Esta variante del patrón crea una cadena .then()
, y puede usarse para encadenar animaciones, o hacer una secuencia de solicitudes HTTP dependientes.
[1, 3, 5, 7, 9].reduce((seq, n) => {
return seq.then(() => {
console.log(n);
return new Promise(res => setTimeout(res, 1000));
});
}, Promise.resolve()).then(
() => console.log('done'),
(e) => console.log(e)
);
// will log 1, 3, 5, 7, 9, 'done' in 1s intervals
Explicación:
- Llamamos a
.reduce()
en una matriz de origen y proporcionamosPromise.resolve()
como un valor inicial. - Cada elemento reducido agregará un
.then()
al valor inicial. -
reduce()
será Promise.resolve (). then (...). then (...). -
.then(successHandler, errorHandler)
manualmente un.then(successHandler, errorHandler)
después de la reducción, para ejecutarsuccessHandler
una vez que se hayan resuelto todos los pasos anteriores. Si algún paso fallara, se ejecutaríaerrorHandler
.
Nota: La reducción "entonces" es una contraparte secuencial de Promise.all()
.
La reducción de "captura"
Esta variante del patrón crea una cadena .catch()
y puede usarse para sondear secuencialmente un conjunto de servidores web para algún recurso duplicado hasta que se encuentre un servidor que funcione.
var working_resource = 5; // one of the values from the source array
[1, 3, 5, 7, 9].reduce((seq, n) => {
return seq.catch(() => {
console.log(n);
if(n === working_resource) { // 5 is working
return new Promise((resolve, reject) => setTimeout(() => resolve(n), 1000));
} else { // all other values are not working
return new Promise((resolve, reject) => setTimeout(reject, 1000));
}
});
}, Promise.reject()).then(
(n) => console.log('success at: ' + n),
() => console.log('total failure')
);
// will log 1, 3, 5, 'success at 5' at 1s intervals
Explicación:
- Llamamos a
.reduce()
en una matriz de origen y proporcionamosPromise.reject()
como un valor inicial. - Cada elemento reducido agregará un
.catch()
al valor inicial. -
reduce()
seráPromise.reject().catch(...).catch(...)
. -
.then(successHandler, errorHandler)
manualmente.then(successHandler, errorHandler)
después de la reducción, para ejecutarsuccessHandler
una vez que se haya resuelto alguno de los pasos anteriores. Si todos los pasos fuesenerrorHandler
, entonces se ejecutaríaerrorHandler
.
Nota: La reducción de "captura" es una contrapartida secuencial de Promise.any()
(como se implementó en bluebird.js
, pero actualmente no está en ECMAScript nativo).
para cada uno con promesas
Es posible aplicar efectivamente una función ( cb
) que devuelve una promesa a cada elemento de una matriz, con cada elemento en espera de ser procesado hasta que se procese el elemento anterior.
function promiseForEach(arr, cb) {
var i = 0;
var nextPromise = function () {
if (i >= arr.length) {
// Processing finished.
return;
}
// Process next function. Wrap in `Promise.resolve` in case
// the function does not return a promise
var newPromise = Promise.resolve(cb(arr[i], i));
i++;
// Chain to finish processing.
return newPromise.then(nextPromise);
};
// Kick off the chain.
return Promise.resolve().then(nextPromise);
};
Esto puede ser útil si necesita procesar eficientemente miles de artículos, uno a la vez. El uso de un bucle for
regular for
crear las promesas los creará todos a la vez y ocupará una cantidad significativa de RAM.
Realizando la limpieza con finalmente ()
Actualmente hay una propuesta (que aún no forma parte del estándar ECMAScript) para agregar una devolución de llamada finally
a las promesas que se ejecutarán independientemente de si la promesa se cumple o se rechaza. Semánticamente, esto es similar a la cláusula finally
del bloque try
.
Usualmente usaría esta funcionalidad para la limpieza:
var loadingData = true;
fetch('/data')
.then(result => processData(result.data))
.catch(error => console.error(error))
.finally(() => {
loadingData = false;
});
Es importante tener en cuenta que la devolución de llamada finally
no afecta el estado de la promesa. No importa el valor que devuelva, la promesa se mantiene en el estado cumplido / rechazado que tenía antes. Por lo tanto, en el ejemplo anterior, la promesa se resolverá con el valor de retorno de processData(result.data)
aunque la devolución de llamada finally
devolvió undefined
.
Con el proceso de normalización sigue siendo en curso, la implementación de las promesas más probable es que no apoyará finally
devoluciones de llamada fuera de la caja. Para las devoluciones de llamada sincrónicas, puede agregar esta funcionalidad con un polyfill sin embargo:
if (!Promise.prototype.finally) {
Promise.prototype.finally = function(callback) {
return this.then(result => {
callback();
return result;
}, error => {
callback();
throw error;
});
};
}
Solicitud de API asíncrona
Este es un ejemplo de una simple llamada GET
API envuelta en una promesa de aprovechar su funcionalidad asíncrona.
var get = function(path) {
return new Promise(function(resolve, reject) {
let request = new XMLHttpRequest();
request.open('GET', path);
request.onload = resolve;
request.onerror = reject;
request.send();
});
};
Se puede hacer un manejo de errores más robusto usando las siguientes funciones onload
y onerror
.
request.onload = function() {
if (this.status >= 200 && this.status < 300) {
if(request.response) {
// Assuming a successful call returns JSON
resolve(JSON.parse(request.response));
} else {
resolve();
} else {
reject({
'status': this.status,
'message': request.statusText
});
}
};
request.onerror = function() {
reject({
'status': this.status,
'message': request.statusText
});
};
Utilizando ES2017 async / await
El mismo ejemplo anterior, Carga de imagen , puede escribirse usando funciones asíncronas . Esto también permite usar el método común de try/catch
para el manejo de excepciones.
function loadImage(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.addEventListener('load', () => resolve(img));
img.addEventListener('error', () => {
reject(new Error(`Failed to load ${url}`));
});
img.src = url;
});
}
(async () => {
// load /image.png and append to #image-holder, otherwise throw error
try {
let img = await loadImage('http://example.com/image.png');
document.getElementById('image-holder').appendChild(img);
}
catch (error) {
console.error(error);
}
})();