aboutsummaryrefslogtreecommitdiff
path: root/files/es/web/javascript/referencia/sentencias/funcion_asincrona/index.html
blob: 573c10fad88e1a8910a08dba411b8e3e40972e00 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
---
title: Función async
slug: Web/JavaScript/Referencia/Sentencias/funcion_asincrona
tags:
  - Declaración
  - Ejemplo
  - JavaScript
  - función
translation_of: Web/JavaScript/Reference/Statements/async_function
---
<div>
<div>{{jsSidebar("Statements")}}</div>

<p>La declaración de función <code><strong>async</strong></code> define una <em>función asíncrona</em>, la cual devuelve un objeto {{jsxref("Global_Objects/AsyncFunction","AsyncFunction")}}.</p>

<div class="noinclude">
<p>Es posible definir también funciones asíncronas a través de una {{jsxref("Operators/async_function", "expresión de función async", "", 1)}}.</p>
</div>
</div>

<div>{{EmbedInteractiveExample("pages/js/statement-async.html", "taller")}}</div>

<p class="hidden">The source for this interactive demo is stored in a GitHub repository. If you'd like to contribute to the interactive demo project, please clone <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> and send us a pull request.</p>

<h2 id="Sintaxis">Sintaxis</h2>

<pre class="syntaxbox">async function <em>name</em>([<em>param</em>[, <em>param</em>[, ... <em>param</em>]]]) {
   <em>statements</em>
}
</pre>

<h3 id="Parámetros">Parámetros</h3>

<dl>
 <dt><code>name</code></dt>
 <dd>El nombre de la función.</dd>
</dl>

<dl>
 <dt><code>param</code></dt>
 <dd>El nombre de un argumento que se debe pasar a la función.</dd>
</dl>

<dl>
 <dt><code>statements</code></dt>
 <dd>Las declaraciones que conforman el cuerpo de la función.</dd>
</dl>

<h3 id="Valor_de_retorno">Valor de retorno</h3>

<p>Un objeto {{jsxref("Global_Objects/AsyncFunction","AsyncFunction")}}, que representa una función asíncrona que ejecuta el código contenido dentro de la función.</p>

<h2 id="Descripción">Descripción</h2>

<p>Cuando se llama a una función <code>async</code>, esta devuelve un elemento {{jsxref("Promise")}}. Cuando la función <code>async</code> devuelve un valor, <code>Promise</code> se resolverá con el valor devuelto. Si la función <code>async</code> genera una excepción o algún valor, <code>Promise</code> se rechazará con el valor generado.</p>

<p>Una función <code>async</code> puede contener una expresión {{jsxref("Operators/await", "await")}}, la cual pausa la ejecución de la función asíncrona y espera la resolución de la <code>Promise</code> pasada y, a continuación, reanuda la ejecución de la función <code>async</code> y devuelve el valor resuelto.</p>

<div class="note">
<p>La finalidad de las funciones <code>async</code>/<code>await</code> es simplificar el comportamiento del uso síncrono de promesas y realizar algún comportamiento específico en un grupo de <code>Promises</code>. Del mismo modo que las <code>Promises</code> son semejantes a las devoluciones de llamadas estructuradas, <code>async</code>/<code>await</code> se asemejan a una combinación de generadores y promesas.</p>
</div>

<h2 id="Ejemplos">Ejemplos</h2>

<h3 id="Ejemplo_sencillo">Ejemplo sencillo</h3>

<pre class="brush: js">function resolveAfter2Seconds(x) {
  return new Promise(resolve =&gt; {
    setTimeout(() =&gt; {
      resolve(x);
    }, 2000);
  });
}


async function add1(x) {
  const a = await resolveAfter2Seconds(20);
  const b = await resolveAfter2Seconds(30);
  return x + a + b;
}

add1(10).then(v =&gt; {
  console.log(v);  // prints 60 after 4 seconds.
});


async function add2(x) {
  const p_a = resolveAfter2Seconds(20);
  const p_b = resolveAfter2Seconds(30);
  return x + await p_a + await p_b;
}

add2(10).then(v =&gt; {
  console.log(v);  // prints 60 after 2 seconds.
});
</pre>

<div class="warning">
<h4 id="No_se_deben_confundir_await_y_Promise.all">No se deben confundir <code>await</code> y <code>Promise.all</code></h4>

<p>En <code>add1</code>, la ejecución se suspende durante dos segundos correspondientes al primer operador <code>await</code>, y luego durante otros dos segundos correspondientes al segundo <code>await</code>. El segundo temporizador no se crea hasta que el primero no se haya disparado ya. En <code>add2</code>, ambos temporizadores se crean y, acto seguido, ambos reciben <code>await</code>. Esto provoca la resolución en dos segundos y no cuatro, ya que los temporizadores se ejecutaron de manera simultánea. Sin embargo, ambas llamadas <code>await</code> aún pueden ejecutarse en series, no en paralelo: esto <strong>no</strong> constituye ninguna aplicación automática de <code>Promise.all</code>. Si se desea aplicar <code>await</code> a dos o más promesas en paralelo, es preciso utilizar <code>Promise.all</code>.</p>
</div>

<h3 id="Reescritura_de_una_cadena_de_promesas_con_una_función_async">Reescritura de una cadena de promesas con una función <code>async</code></h3>

<p>Una API que devuelva una {{jsxref("Promise")}} tendrá como resultado una cadena de promesas, y dividirá la función en muchas partes. Estudie este código:</p>

<pre class="brush: js">function getProcessedData(url) {
  return downloadData(url) // returns a promise
    .catch(e =&gt; {
      return downloadFallbackData(url)  // returns a promise
    })
    .then(v =&gt; {
      return processDataInWorker(v); // returns a promise
    });
}
</pre>

<p>Es posible reescribirlo utilizando un solo operador <code>async</code> de esta manera:</p>

<pre class="brush: js">async function getProcessedData(url) {
  let v;
  try {
    v = await downloadData(url);
  } catch(e) {
    v = await downloadFallbackData(url);
  }
  return processDataInWorker(v);
}
</pre>

<p>Observe que, en el ejemplo anterior, no hay ninguna instrucción <code>await</code> dentro de la instrucción <code>return</code>, porque el valor de retorno de una <code>async function</code> queda implícitamente dentro de un {{jsxref("Promise.resolve")}}.</p>

<h2 id="Especificaciones">Especificaciones</h2>

<table class="standard-table">
 <thead>
  <tr>
   <th scope="col">Especificación</th>
   <th scope="col">Estado</th>
   <th scope="col">Comentario</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-async-function-definitions', 'Función async')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td>Definición inicial en ES2017.</td>
  </tr>
  <tr>
   <td>{{SpecName('ES8', '#sec-async-function-definitions', 'Función async')}}</td>
   <td>{{Spec2('ES8')}}</td>
   <td> </td>
  </tr>
 </tbody>
</table>

<h2 id="Compatibilidad_entre_navegadores">Compatibilidad entre navegadores</h2>

<div>


<p>{{Compat("javascript.statements.async_function")}}</p>
</div>

<h2 id="Véase_también">Véase también</h2>

<ul>
 <li>{{jsxref("Operators/async_function", "Expresión de función async")}}</li>
 <li>Objeto {{jsxref("AsyncFunction")}}</li>
 <li>{{jsxref("Operators/await", "await")}}</li>
 <li><a href="http://innolitics.com/10x/javascript-decorators-for-promise-returning-functions/">«Decorar funciones async de JavaScript» en innolitics.com</a> (en inglés)</li>
</ul>