script defer async javascript ecmascript-6 async-await ecmascript-2017

javascript - defer - script async



ES2017-Async vs. Rendimiento (4)

No entiendo por qué es necesario tener la palabra clave async antes de la palabra clave de función.

Por la misma razón que tenemos el símbolo * antes de las funciones del generador: marcan la función como extraordinaria. En este sentido, son bastante similares: agregan un marcador visual que indica que el cuerpo de esta función no se ejecuta solo, sino que puede intercalarse arbitrariamente con otro código.

  • El * denota una función de generador, que siempre devolverá un generador que puede ser avanzado (y detenido) desde el exterior al consumirlo de manera similar a un iterador.
  • El async denota una función asíncrona, que siempre devolverá una promesa que depende de otras promesas y cuya ejecución es concurrente a otras operaciones asíncronas (y podría cancelarse desde el exterior).

Es cierto que la palabra clave no es estrictamente necesaria y el tipo de función podría determinarse si las palabras clave respectivas ( yield(*) / await ) aparecen en su cuerpo, pero eso llevaría a un código menos mantenible:

  • menos comprensible, porque necesitas escanear todo el cuerpo para determinar el tipo
  • más errorprone, porque es fácil romper una función agregando / eliminando esas palabras clave sin obtener un error de sintaxis

una función normal, cuya ejecución esperará a que termine el cuerpo del orificio hasta que se cumplan todas las esperas

Parece que quieres una función de bloqueo, lo cual es una muy mala idea en una configuración concurrente.

Estoy confundido acerca de la discusión actual de agregar funciones asíncronas y la palabra clave le await al próximo EcmaScript.

No entiendo por qué es necesario tener la palabra clave async antes de la palabra clave de function .

Desde mi punto de vista, la palabra clave await para esperar el resultado de un generador o promesa realizada , el return una función debería ser suficiente.

await debería ser fácilmente utilizable dentro de las funciones normales y las funciones del generador sin marcador async adicional.

Y si necesito crear una función que pueda ser utilizada como resultado de una await , simplemente uso una promesa.

Mi razón para preguntar es this buena explicación, de donde viene el siguiente ejemplo:

async function setupNewUser(name) { var invitations, newUser = await createUser(name), friends = await getFacebookFriends(name); if (friends) { invitations = await inviteFacebookFriends(friends); } // some more logic }

También se podría hacer como una función normal, si la ejecución de una función esperará a que termine la función del agujero hasta que se cumplan todas las esperas.

function setupNewUser(name) { var invitations, newUser = await createUser(name), friends = await getFacebookFriends(name); if (friends) { invitations = await inviteFacebookFriends(friends); } // return because createUser() and getFacebookFriends() and maybe inviteFacebookFriends() finished their awaited result. }

En mi opinión, toda la ejecución de la función se mantiene hasta que se complete el siguiente tick (esperar el cumplimiento). La diferencia con la función de generador es que el siguiente () está activando y cambiando el valor del objeto y el campo de finalización. En cambio, una función simplemente devolverá el resultado cuando se haga y el disparador es un disparador interno de función como un ciclo de tiempo.


Al marcar una función como async , le está diciendo a JS que siempre devuelva una Promesa.

Debido a que siempre devolverá una Promesa, también puede esperar promesas dentro de su propio bloque. Imagínelo como una cadena de Promise gigante: lo que sucede internamente a la función se atornilla efectivamente a su bloque .then() interno, y lo que se devuelve es el .then() final en la cadena.

Por ejemplo, esta función ...

async function test() { return ''hello world''; }

... devuelve una Promesa. Así que puedes ejecutarlo como uno, .then() y todo.

test().then(message => { // message = ''hello world'' });

Asi que...

async function test() { const user = await getUser(); const report = await user.getReport(); report.read = true return report; }

Es más o menos análogo a ...

function test() { return getUser().then(function (user) { return user.getReport().then(function (report) { report.read = true; return report; }); }); }

En ambos casos, la devolución de llamada pasada a test().then() recibirá el report como su primer parámetro.

Los generadores (es decir, marcar una función * y usar la palabra clave de yield ) son un concepto completamente diferente. No usan las promesas. De manera efectiva, le permiten ''saltar'' entre diferentes partes de su código, obteniendo un resultado desde el interior de una función y luego saltando de nuevo a ese punto y reanudando para el siguiente bloque de rendimiento.

Aunque se sienten algo similares (es decir, que la ejecución se "detiene" hasta que algo sucede en otro lugar), async/await solo te da esa ilusión porque interfiere con el orden interno de la ejecución de Promise . En realidad no está esperando, solo se baraja cuando ocurren las devoluciones de llamada.

Los generadores, por el contrario, se implementan de manera diferente para que el generador pueda mantener el estado y ser iterado. De nuevo, nada que ver con Promesas.

La línea está aún más borrosa porque en el momento actual de la escritura, el soporte para async / await es un susto; Chakracore lo soporta de forma nativa, y V8 lo tiene disponible próximamente . Mientras tanto, los transpilers como Babel le permiten escribir async/await y convertir el código en generators . Es un error concluir que los generadores y async / await son, por lo tanto, lo mismo; no lo son ... da la casualidad de que puede bastardizar cómo funciona el yield junto con Promises para obtener un resultado similar.

Actualización: noviembre 2017

Node LTS ahora tiene soporte nativo async/await , por lo que nunca debe usar generadores para simular Promesas.


El motivo de la palabra clave asíncrona en el frente es simple, por lo que sabe que el valor de retorno se transformará en una promesa. Si no hubiera una palabra clave, ¿cómo sabría el intérprete hacer esto? Creo que esta fue la primera vez que se introdujo en C # y EcmaScript está tomando un montón de cosas de TypeScript. TypeScript y C # son concebidos por Anders Hejlsberg y son similares. digamos que tienes una función (esta es solo para tener un trabajo asíncrono)

function timeoutPromise() { return (new Promise(function(resolve, reject) { var random = Math.random()*1000; setTimeout( function() { resolve(random); }, random); })); }

esta función nos hará esperar por un tiempo aleatorio y devolverá una Promesa (si utiliza jQuery La Promesa es similar a la Diferencia). Para usar esta función hoy escribirías algo como esto.

function test(){ timeoutPromise().then(function(waited){ console.log(''I waited'' + waited); }); }

Y esto está bien. Ahora vamos a intentar devolver el mensaje de registro

function test(){ return timeoutPromise().then(function(waited){ var message = ''I waited'' + waited; console.log(message); return message; //this is where jQuery Deferred is different then a Promise and better in my opinion }); }

Ok, esto no es malo, pero hay dos declaraciones de retorno y una función en el código.

Ahora con async esto se verá así

async function test(){ var message = ''I waited'' + (await timeoutPromise()); console.log(message); return message; }

El código es corto y en línea. Si escribiste mucho .then () o. hecho () sabes cuán ilegible puede ser el código.

Ahora por qué la palabra clave asíncrona delante de la función. Bueno, esto es para indicar que su valor de retorno no es lo que se devuelve. En teoría, podría escribir esto (Esto puede hacerse en c # No sé si js lo permitirá ya que no está hecho).

async function test(wait){ if(wait == true){ return await timeoutPromise(); } return 5; }

Usted ve, devuelve un número, pero la devolución real será una Promesa que no tiene que usar return new Promise(function(resolve, reject) { resolve(5);}; ya que no puede esperar un número, solo un Promise await test(false) lanzará una excepción y await test(true) no si no indica async en frente.


Todas estas respuestas brindan argumentos válidos de por qué la palabra clave asíncrona es una buena cosa, pero ninguna de ellas en realidad menciona la razón real por la que tuvo que agregarse a la especificación.

La razón es que este era un JS pre-ES7 válido.

function await(x) { return ''awaiting '' + x } function foo() { return(await(42)) }

De acuerdo con su lógica, foo() devolvería la Promise{42} o "awaiting 42" ? (Devolver una Promesa rompería la compatibilidad hacia atrás)

Entonces, la respuesta es: await es un identificador regular y solo se trata como una palabra clave dentro de las funciones asíncronas, por lo que deben marcarse de alguna manera.

Dato curioso: la especificación original propuso una function^ foo() {} más ligera function^ foo() {} para la sintaxis asíncrona.