Las funciones asíncronas , una característica de ES2017 , hacen que el código asíncrono se vea sincronizado mediante el uso de promesas (una forma particular de código asíncrono) y la await
palabra clave. Observe también en los ejemplos de código debajo de la palabra clave async
delante de la function
palabra clave que significa una función asíncrona / espera. La await
palabra clave no funcionará sin estar en una función preestablecida con la async
palabra clave. Dado que actualmente no hay ninguna excepción a esto, eso significa que no funcionará ninguna espera de nivel superior (el nivel superior espera, lo que significa una espera fuera de cualquier función). Aunque hay una propuesta para el nivel superiorawait
.
ES2017 fue ratificado (es decir, finalizado) como el estándar para JavaScript el 27 de junio de 2017. Async aguardando ya puede funcionar en su navegador, pero si no puede seguir utilizando la funcionalidad utilizando un transpiler javascript como babel o traceur . Chrome 55 tiene soporte completo de funciones asíncronas. Entonces, si tiene un navegador más nuevo, puede probar el código a continuación.
Consulte la tabla de compatibilidad de kangax es2017 para ver la compatibilidad del navegador.
Aquí hay un ejemplo de función de espera asíncrona llamada doAsync
que toma tres pausas de un segundo e imprime la diferencia horaria después de cada pausa desde la hora de inicio:
function timeoutPromise (time) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(Date.now());
}, time)
})
}
function doSomethingAsync () {
return timeoutPromise(1000);
}
async function doAsync () {
var start = Date.now(), time;
console.log(0);
time = await doSomethingAsync();
console.log(time - start);
time = await doSomethingAsync();
console.log(time - start);
time = await doSomethingAsync();
console.log(time - start);
}
doAsync();
Cuando la palabra clave de espera se coloca antes de un valor de promesa (en este caso, el valor de promesa es el valor devuelto por la función doSomethingAsync), la palabra clave de espera detendrá la ejecución de la llamada de función, pero no detendrá ninguna otra función y continuará ejecutando otro código hasta que se resuelva la promesa. Después de que la promesa se resuelva, desenvolverá el valor de la promesa y puede pensar en la expresión de esperar y prometer como ahora reemplazada por ese valor desenvuelto.
Entonces, dado que esperar solo pausa, espera y luego desenvuelve un valor antes de ejecutar el resto de la línea, puede usarlo para bucles y llamadas a funciones internas como en el ejemplo a continuación, que recopila las diferencias de tiempo esperadas en un conjunto e imprime el conjunto.
function timeoutPromise (time) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(Date.now());
}, time)
})
}
function doSomethingAsync () {
return timeoutPromise(1000);
}
// this calls each promise returning function one after the other
async function doAsync () {
var response = [];
var start = Date.now();
// each index is a promise returning function
var promiseFuncs= [doSomethingAsync, doSomethingAsync, doSomethingAsync];
for(var i = 0; i < promiseFuncs.length; ++i) {
var promiseFunc = promiseFuncs[i];
response.push(await promiseFunc() - start);
console.log(response);
}
// do something with response which is an array of values that were from resolved promises.
return response
}
doAsync().then(function (response) {
console.log(response)
})
La función asíncrona en sí misma devuelve una promesa, por lo que puede usarla como una promesa con el encadenamiento como lo hago arriba o dentro de otra función de espera asíncrona.
La función anterior esperaría cada respuesta antes de enviar otra solicitud. Si desea enviar las solicitudes simultáneamente, puede usar Promise.all .
// no change
function timeoutPromise (time) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(Date.now());
}, time)
})
}
// no change
function doSomethingAsync () {
return timeoutPromise(1000);
}
// this function calls the async promise returning functions all at around the same time
async function doAsync () {
var start = Date.now();
// we are now using promise all to await all promises to settle
var responses = await Promise.all([doSomethingAsync(), doSomethingAsync(), doSomethingAsync()]);
return responses.map(x=>x-start);
}
// no change
doAsync().then(function (response) {
console.log(response)
})
Si la promesa posiblemente se rechaza, puede envolverla en un try catch u omitir el try catch y dejar que el error se propague a la llamada catch de las funciones asíncronas / en espera. Debe tener cuidado de no dejar errores de promesa no controlados, especialmente en Node.js. A continuación se muestran algunos ejemplos que muestran cómo funcionan los errores.
function timeoutReject (time) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
reject(new Error("OOPS well you got an error at TIMESTAMP: " + Date.now()));
}, time)
})
}
function doErrorAsync () {
return timeoutReject(1000);
}
var log = (...args)=>console.log(...args);
var logErr = (...args)=>console.error(...args);
async function unpropogatedError () {
// promise is not awaited or returned so it does not propogate the error
doErrorAsync();
return "finished unpropogatedError successfully";
}
unpropogatedError().then(log).catch(logErr)
async function handledError () {
var start = Date.now();
try {
console.log((await doErrorAsync()) - start);
console.log("past error");
} catch (e) {
console.log("in catch we handled the error");
}
return "finished handledError successfully";
}
handledError().then(log).catch(logErr)
// example of how error propogates to chained catch method
async function propogatedError () {
var start = Date.now();
var time = await doErrorAsync() - start;
console.log(time - start);
return "finished propogatedError successfully";
}
// this is what prints propogatedError's error.
propogatedError().then(log).catch(logErr)
Si va aquí , puede ver las propuestas terminadas para las próximas versiones de ECMAScript.
Una alternativa a esto que se puede usar solo con ES2015 (ES6) es usar una función especial que envuelva una función de generador. Las funciones generadoras tienen una palabra clave de rendimiento que puede usarse para replicar la palabra clave de espera con una función circundante. La palabra clave de rendimiento y la función de generador tienen un propósito mucho más general y pueden hacer muchas más cosas que lo que hace la función de espera asíncrona. Si quieres un envoltorio función de generador que se puede utilizar para la réplica asíncrona esperan que volvería a la salida co.js . Por cierto, la función de co, al igual que las funciones de espera asíncrona, devuelve una promesa. Honestamente, en este punto, la compatibilidad del navegador es casi la misma tanto para las funciones de generador como para las funciones asíncronas, por lo que si solo desea la funcionalidad de espera asíncrona, debe usar las funciones asíncronas sin co.js.
El soporte del navegador es bastante bueno ahora para las funciones asíncronas (a partir de 2017) en todos los principales navegadores actuales (Chrome, Safari y Edge) excepto IE.