He estado revisando async
/ await
y después de revisar varios artículos, decidí probar las cosas yo mismo. Sin embargo, parece que no puedo entender por qué esto no funciona:
async function main() {
var value = await Promise.resolve('Hey there');
console.log('inside: ' + value);
return value;
}
var text = main();
console.log('outside: ' + text);
La consola genera lo siguiente (nodo v8.6.0):
> fuera: [promesa de objeto]
> dentro: Hola
¿Por qué el mensaje de registro dentro de la función se ejecuta después? Pensé que la razón async
/ await
fue creado fue para realizar una ejecución sincrónica usando tareas asincrónicas.
¿Hay alguna manera de usar el valor devuelto dentro de la función sin usar un .then()
after main()
?
await
no es más que azúcar para lathen
sintaxis de promesa .main
async/await
es parte de ES2017, no ES7 (ES2016)Respuestas:
Porque
main
devuelve una promesa; todas lasasync
funciones lo hacen.En el nivel superior, debes:
Utilice una
async
función de nivel superior que nunca rechace (a menos que desee errores de "rechazo no controlado"), oUsar
then
ycatch
, o(¡Próximamente!) Utilice el nivel superior
await
, una propuesta que ha alcanzado la Etapa 3 en el proceso que permite el uso de nivel superiorawait
en un módulo.# 1 -
async
Función de nivel superior que nunca rechazaNote el
catch
; debe manejar los rechazos de promesa / excepciones asíncronas, ya que nada más lo hará ; no tienes quien llama para pasarlos. Si lo prefiere, puede hacerlo con el resultado de llamarlo a través de lacatch
función (en lugar detry
/catch
sintaxis):... que es un poco más conciso (por eso me gusta).
O, por supuesto, no maneje los errores y solo permita el error de "rechazo no controlado".
# 2 -
then
ycatch
Se
catch
llamará al controlador si se producen errores en la cadena o en suthen
controlador. (Asegúrese de que sucatch
controlador no arroje errores, ya que no hay nada registrado para manejarlos).O ambos argumentos para
then
:Nuevamente, observe que estamos registrando un controlador de rechazo. Pero de esta forma, asegúrese de que ninguna de sus
then
devoluciones de llamada no arroje ningún error, no hay nada registrado para manejarlos.# 3 de nivel superior
await
en un móduloNo se puede usar
await
en el nivel superior de un script que no sea de módulo, pero la propuesta de nivel superiorawait
( Etapa 3 ) le permite usarlo en el nivel superior de un módulo. Es similar al uso de unasync
contenedor de funciones de nivel superior (# 1 arriba) en que no desea que su código de nivel superior rechace (arroje un error) porque eso dará como resultado un error de rechazo no controlado. Entonces, a menos que desee tener ese rechazo no controlado cuando las cosas salen mal, como con el n. ° 1, querrá incluir su código en un controlador de errores:Tenga en cuenta que si hace esto, cualquier módulo que importe desde su módulo esperará hasta que se cumpla la promesa que está
await
cumpliendo; cuandoawait
se evalúa un módulo que utiliza el nivel superior , básicamente devuelve una promesa al cargador de módulos (como lo hace unaasync
función), que espera hasta que se cumpla esa promesa antes de evaluar los cuerpos de los módulos que dependen de él.fuente
async
/await
son azúcar sintáctica alrededor de las promesas (el buen tipo de azúcar :-)). No sólo estás pensando en él como una promesa de regresar; En realidad lo hace. ( Detalles .)async
opción todo primero. Para la función de nivel superior, puedo verla de cualquier manera (principalmente debido a dos niveles de sangría en laasync
versión).await
propuesta de nivel superior ha alcanzado la Etapa 3. :-)El nivel superior se
await
ha movido a la etapa 3, por lo que la respuesta a su pregunta ¿Cómo puedo usar async / wait en el nivel superior? es simplemente agregarawait
la llamada amain()
:O solo:
Tenga en cuenta que todavía solo está disponible en [email protected] .
Si está utilizando TypeScript , aterrizó en 3.8 .
v8 ha agregado soporte en módulos.
También es compatible con Deno (como comentó gonzalo-bahamondez).
fuente
La solución real a este problema es abordarlo de manera diferente.
Probablemente su objetivo es algún tipo de inicialización que generalmente ocurre en el nivel superior de una aplicación.
La solución es garantizar que solo haya una única declaración de JavaScript en el nivel superior de su aplicación. Si solo tiene una declaración en la parte superior de su aplicación, puede usar async / wait en cualquier otro lugar (sujeto a las reglas de sintaxis normales)
Dicho de otra manera, envuelva todo su nivel superior en una función para que ya no sea el nivel superior y eso resuelva la cuestión de cómo ejecutar async / wait en el nivel superior de una aplicación, no lo hace.
Así debería verse el nivel superior de su aplicación:
fuente
application()
sea asíncrono?Para dar más información sobre las respuestas actuales:
El contenido de un
node.js
archivo está actualmente concatenado, de forma similar a una cadena, para formar un cuerpo de función.Por ejemplo, si tiene un archivo
test.js
:Luego
node.js
secretamente concatenará una función que se ve así:Lo más importante a tener en cuenta es que la función resultante NO es una función asíncrona. ¡Entonces no puedes usar el término
await
directamente dentro de él!Pero supongamos que necesita trabajar con las promesas en este archivo, entonces hay dos métodos posibles:
await
directamente dentro de la funciónawait
La opción 1 requiere que
async
creemos un nuevo alcance (y ESTE alcance puede serlo , porque tenemos control sobre él):La opción 2 requiere que usemos la API de promesa orientada a objetos (el paradigma menos bonito pero igualmente funcional de trabajar con promesas)
Personalmente espero que, si es viable, node.js concatene el código por defecto en una
async
función. Eso eliminaría este dolor de cabeza.fuente
El nivel superior de espera es una característica del próximo estándar EcmaScript. Actualmente, puede comenzar a usarlo con TypeScript 3.8 (en la versión RC en este momento).
Cómo instalar TypeScript 3.8
Puede comenzar a usar TypeScript 3.8 instalándolo desde npm usando el siguiente comando:
En este momento, debe agregar la
rc
etiqueta para instalar la última versión de mecanografiado 3.8.fuente
Como se
main()
ejecuta de forma asincrónica, devuelve una promesa. Tienes que obtener el resultado en elthen()
método. Y debido a que lasthen()
devoluciones también son prometedoras, debe llamarprocess.exit()
para finalizar el programa.fuente
exit()
para indicar si ocurrió un error.process.exit(1)