[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/async_function [Back]  [Original]

async function - JavaScript | MDN

Esta pgina ha sido traducida del ingls por la comunidad. Aprende ms y nete a la comunidad de MDN Web Docs.

View in English Always switch to English

async function

Baseline Widely available

This feature is well established and works across many devices and browser versions. Its been available across browsers since abril de 2017.

La declaracin async function crea un enlace de una nueva funcin asncrona a un nombre dado. La palabra clave await est permitida dentro del cuerpo de la funcin, lo que permite escribir un comportamiento asncrono basado en promesas de un estilo ms limpio y evitar la necesidad de configurar explcitamente cadenas de promesas.

Tambin puedes definir funciones asncronas usando la expresin async function.

In this article

Prubalo

function resolveAfter2Seconds() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("resolved");
    }, 2000);
  });
}

async function asyncCall() {
  console.log("llamando");
  const result = await resolveAfter2Seconds();
  console.log(result);
  // Salida esperada: "resolved"
}

asyncCall();

Sintaxis

js
async function name(param0) {
  sentencias
}
async function name(param0, param1) {
  sentencias
}
async function name(param0, param1, /* , */ paramN) {
  sentencias
}

Nota: No puede haber un terminador de lnea entre async y function; de lo contrario, se inserta un punto y coma automticamente, lo que provoca que async se convierta en un identificador y el resto en una declaracin de function.

Parmetros

name

El nombre de la funcin.

param Opcional

El nombre de un parmetro formal para la funcin. Para conocer la sintaxis de los parmetros, consulta la referencia de Funciones.

statements Opcional

Las sentencias que conforman el cuerpo de la funcin. Se puede utilizar el mecanismo await.

Descripcin

Una declaracin async function crea un objeto AsyncFunction. Cada vez que se llama a una funcin asncrona, esta devuelve una nueva Promise, que se resolver con el valor devuelto por la funcin asncrona, o se rechazar con una excepcin no capturada dentro de la misma.

Las funciones asncronas pueden contener cero o ms expresiones await. Las expresiones await hacen que las funciones que devuelven promesas se comporten como si fueran sncronas, al suspender la ejecucin hasta que la promesa devuelta se cumpla o se rechace. El valor resuelto de la promesa se trata como el valor de retorno de la expresin await. El uso de async y await permite el uso de bloques ordinarios try / catch alrededor del cdigo asncrono.

Nota: La palabra clave await solo es vlida dentro de funciones asncronas en el cdigo JavaScript normal. Si la usas fuera del cuerpo de una funcin asncrona, obtendrs un SyntaxError.

await se puede usar por s solo con mdulos de JavaScript.

Nota: El propsito de async/await es simplificar la sintaxis necesaria para consumir APIs basadas en promesas. El comportamiento de async/await es similar a combinar generadores y promesas.

Las funciones asncronas siempre devuelven una promesa. Si el valor de retorno de una funcin asncrona no es explcitamente una promesa, se envolver implcitamente en una promesa.

Por ejemplo, considera el siguiente cdigo:

js
async function foo() {
  return 1;
}

Es similar a:

js
function foo() {
  return Promise.resolve(1);
}

Ten en cuenta que, aunque el valor de retorno de una funcin asncrona se comporta como si estuviera envuelto en un Promise.resolve, no son equivalentes. Una funcin asncrona devolver una referencia diferente, mientras que Promise.resolve devuelve la misma referencia si el valor dado es una promesa. Esto puede ser un problema cuando deseas verificar la igualdad entre una promesa y el valor de retorno de una funcin asncrona.

js
const p = new Promise((res, rej) => {
  res(1);
});

async function asyncReturn() {
  return p;
}

function basicReturn() {
  return Promise.resolve(p);
}

console.log(p === basicReturn()); // true
console.log(p === asyncReturn()); // false

Se puede pensar en el cuerpo de una funcin async como si estuviera dividido por cero o ms expresiones await. El cdigo de nivel superior, hasta e incluyendo la primera expresin await (si la hay), se ejecuta de forma sncrona. De esta manera, una funcin asncrona sin una expresin await se ejecutar de forma sncrona. Sin embargo, si hay una expresin await dentro del cuerpo de la funcin, la funcin asncrona siempre se completar de forma asncrona.

Por ejemplo:

js
async function foo() {
  await 1;
}

Tambin es equivalente a:

js
function foo() {
  return Promise.resolve(1).then(() => undefined);
}

El cdigo despus de cada expresin await puede considerarse como si existiera en un callback .then. De esta manera, se construye progresivamente una cadena de promesas con cada paso reentrante a travs de la funcin. El valor de retorno forma el ltimo eslabn de la cadena.

En el siguiente ejemplo, esperamos sucesivamente dos promesas. El progreso a travs de la funcin foo se realiza en tres etapas.

  1. La primera lnea del cuerpo de la funcin foo se ejecuta de forma sncrona, con la expresin await configurada con la promesa pendiente. El progreso a travs de foo se suspende y el control se devuelve a la funcin que llam a foo.
  2. Tiempo despus, cuando la primera promesa se ha cumplido o rechazado, el control vuelve a entrar en foo. El resultado del cumplimiento de la primera promesa (si no fue rechazada) se devuelve desde la expresin await. Aqu, 1 se asigna a result1. El progreso contina y se evala la segunda expresin await. Nuevamente, el progreso a travs de foo se suspende y se cede el control.
  3. Tiempo despus, cuando la segunda promesa se ha cumplido o rechazado, el control vuelve a entrar en foo. El resultado de la resolucin de la segunda promesa se devuelve desde la segunda expresin await. Aqu, 2 se asigna a result2. El control se mueve a la expresin de retorno (si la hay). El valor de retorno por defecto undefined se devuelve como el valor de resolucin de la promesa actual.
js
async function foo() {
  const result1 = await new Promise((resolve) =>
    setTimeout(() => resolve("1")),
  );
  const result2 = await new Promise((resolve) =>
    setTimeout(() => resolve("2")),
  );
}
foo();

Observa cmo la cadena de promesas no se construye de una sola vez. En su lugar, la cadena se construye por etapas, a medida que el control se cede y retorna sucesivamente de la funcin async. Como resultado, debemos tener en cuenta el comportamiento del manejo de errores cuando trabajamos con operaciones asncronas concurrentes.

Por ejemplo, en el siguiente cdigo se lanzar un error de rechazo de promesa no controlado, incluso si se ha configurado un manejador .catch ms adelante en la cadena de promesas. Esto se debe a que p2 no se 'conectar' a la cadena de promesas hasta que el control retorne de p1.

js
async function foo() {
  const p1 = new Promise((resolve) => setTimeout(() => resolve("1"), 1000));
  const p2 = new Promise((_, reject) =>
    setTimeout(() => reject(new Error("failed")), 500),
  );
  const results = [await p1, await p2]; // No hagas esto! Usa Promise.all o Promise.allSettled en su lugar.
}
foo().catch(() => {}); // Intento de silenciar todos los errores...

Las declaraciones async function se comportan de manera similar a las declaraciones function: se elevan (hoisting) hacia la parte superior de su mbito y pueden llamarse desde cualquier lugar del mismo, y solo pueden redeclararse en ciertos contextos.

Ejemplos

Funciones asncronas y orden de ejecucin

js
function resolveAfter2Seconds() {
  console.log("iniciando promesa lenta");
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("slow");
      console.log("promesa lenta terminada");
    }, 2000);
  });
}

function resolveAfter1Second() {
  console.log("iniciando promesa rpida");
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("fast");
      console.log("promesa rpida terminada");
    }, 1000);
  });
}

async function sequentialStart() {
  console.log("== inicia sequentialStart ==");

  // 1. Inicia un temporizador, y registra el resultado cuando termine.
  const slow = resolveAfter2Seconds();
  console.log(await slow);

  // 2. Inicia el siguiente temporizador despus de esperar al anterior.
  const fast = resolveAfter1Second();
  console.log(await fast);

  console.log("== sequentialStart finalizado ==");
}

async function sequentialWait() {
  console.log("== inicia sequentialWait ==");

  // 1. Inicia dos temporizadores sin esperar uno al otro.
  const slow = resolveAfter2Seconds();
  const fast = resolveAfter1Second();

  // 2. Espera a que el temporizador lento finalice, y luego registra el resultado.
  console.log(await slow);
  // 3. Espera a que el temporizador rpido finalice, y luego registra el resultado.
  console.log(await fast);

  console.log("== sequentialWait finalizado ==");
}

async function concurrent1() {
  console.log("== inicia concurrent1 ==");

  // 1. Inicia dos temporizadores concurrentemente y espera a que ambos finalicen.
  const results = await Promise.all([
    resolveAfter2Seconds(),
    resolveAfter1Second(),
  ]);
  // 2. Registra los resultados juntos.
  console.log(results[0]);
  console.log(results[1]);

  console.log("== concurrent1 finalizado ==");
}

async function concurrent2() {
  console.log("== inicia concurrent2 ==");

  // 1. Inicia dos temporizadores concurrentemente, y registra inmediatamente despus de que cada uno termine.
  await Promise.all([
    (async () => console.log(await resolveAfter2Seconds()))(),
    (async () => console.log(await resolveAfter1Second()))(),
  ]);
  console.log("== concurrent2 finalizado ==");
}

sequentialStart(); // despus de 2 segundos, registra "slow", luego despus de 1 segundo ms, "fast"

// espera a que lo anterior termine
setTimeout(sequentialWait, 4000); // despus de 2 segundos, registra "slow" y luego "fast"

// espera de nuevo
setTimeout(concurrent1, 7000); // lo mismo que sequentialWait

// espera de nuevo
setTimeout(concurrent2, 10000); // despus de 1 segundo, registra "fast", luego despus de 1 segundo ms, "slow"

await y concurrencia

En sequentialStart, la ejecucin se suspende 2 segundos para el primer await y luego otro segundo para el segundo await. El segundo temporizador no se crea hasta que el primero ya se ha activado, por lo que el cdigo termina despus de 3 segundos.

En sequentialWait, ambos temporizadores se crean y luego se esperan con await. Los temporizadores se ejecutan de forma concurrente, lo que significa que el cdigo termina en 2 segundos en lugar de 3; es decir, lo que tarde el temporizador ms lento. Sin embargo, las llamadas await se siguen ejecutando en serie, lo que significa que el segundo await esperar a que termine el primero. En este caso, el resultado del temporizador ms rpido se procesa despus del ms lento.

Si deseas realizar otras tareas de forma segura despus de que dos o ms tareas se ejecuten concurrentemente y finalicen, debes usar await en una llamada a Promise.all() o Promise.allSettled() antes de dicha tarea.

Advertencia: Las funciones sequentialWait y concurrent1 no son funcionalmente equivalentes.

En sequentialWait, si la promesa fast se rechaza antes de que la promesa slow se cumpla, se producir un error de rechazo de promesa no manejado, independientemente de si quien realiza la llamada ha configurado una clusula catch.

En concurrent1, Promise.all conecta la cadena de promesas de una sola vez, lo que significa que la operacin fallar de inmediato (fail-fast) independientemente del orden de rechazo de las promesas, y el error siempre ocurrir dentro de la cadena de promesas configurada, permitiendo que se capture de la forma habitual.

Reescritura de una cadena de promesas con una funcin asncrona

Una API que devuelve una Promise dar lugar a una cadena de promesas y divide la funcin en muchas partes. Considera el siguiente cdigo:

js
function getProcessedData(url) {
  return downloadData(url) // devuelve una promesa
    .catch((e) => downloadFallbackData(url)) // devuelve una promesa
    .then((v) => processDataInWorker(v)); // devuelve una promesa
}

Se puede reescribir con una sola funcin asncrona de la siguiente manera:

js
async function getProcessedData(url) {
  let v;
  try {
    v = await downloadData(url);
  } catch (e) {
    v = await downloadFallbackData(url);
  }
  return processDataInWorker(v);
}

Alternativamente, puedes encadenar la promesa con catch():

js
async function getProcessedData(url) {
  const v = await downloadData(url).catch((e) => downloadFallbackData(url));
  return processDataInWorker(v);
}

En las dos versiones reescritas, observa que no hay una sentencia await despus de la palabra clave return, aunque eso tambin sera vlido: el valor de retorno de una funcin asncrona se envuelve implcitamente en Promise.resolve, si no es ya una promesa en s misma (como en los ejemplos).

Especificaciones

Specification
ECMAScript 2027 LanguageSpecification
# sec-async-function-definitions

Compatibilidad con navegadores

Vase tambin


Web Proxy Viewer  |  New URL  |  Original Page