aboutsummaryrefslogtreecommitdiff
path: root/files/es/web/javascript/referencia/objetos_globales/promise/index.html
blob: 58a2319c2f9e304ba2f94291650459a2cf52bc1a (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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
---
title: Promise
slug: Web/JavaScript/Referencia/Objetos_globales/Promise
tags:
  - ECMAScript6
  - JavaScript
  - Promesa
  - Promise
translation_of: Web/JavaScript/Reference/Global_Objects/Promise
---
<div>{{JSRef}}</div>

<p>El objeto <strong><code>Promise</code></strong> (Promesa) es usado para computaciones asíncronas. Una promesa representa un valor que puede estar disponible ahora, en el futuro, o nunca.</p>

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

<pre class="syntaxbox notranslate">new Promise( /* ejecutor */ function(resolver, rechazar) { ... } );</pre>

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

<dl>
 <dt>ejecutor</dt>
 <dd>Una función con los argumentos <code>resolver</code> y <code>rechazar</code>. La función <code>ejecutor</code> es ejecutada inmediatamente por la implementación de la Promesa, pasándole las funciones <code>resolver</code> y <code>rechazar</code> (el ejecutor es llamado incluso antes de que el constructor de la <code>Promesa</code> devuelva el objeto creado). Las funciones <code>resolver</code> y <code>rechazar</code>, al ser llamadas, resuelven o rechazan la promesa, respectivamente. Normalmente el ejecutor inicia un trabajo asíncrono, y luego, una vez que es completado, llama a la función <code>resolver</code> para resolver la promesa o la rechaza si ha ocurrido un error.<br>
 Si un error es lanzado en la función ejecutor, la promesa es rechazada y el valor de retorno del ejecutor es rechazado.</dd>
</dl>

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

<p>Una <strong>Promesa</strong> es un proxy para un valor no necesariamente conocido en el momento que es creada la promesa. Permite asociar manejadores que actuarán asincrónicamente sobre un eventual valor en caso de éxito, o la razón de falla en caso de una falla. Esto permite que métodos asíncronos devuelvan valores como si fueran síncronos: en vez de inmediatamente retornar el valor final, el método asíncrono devuelve una <em>promesa</em> de suministrar el valor en algún momento en el futuro.</p>

<p>Una <code>Promesa</code> se encuentra en uno de los siguientes estados:</p>

<ul>
 <li><em>pendiente (pending)</em>: estado inicial, no cumplida o rechazada.</li>
 <li><em>cumplida (fulfilled)</em>: significa que la operación se completó satisfactoriamente.</li>
 <li><em>rechazada (rejected)</em>: significa que la operación falló.</li>
</ul>

<p>Una promesa pendiente puede ser <em>cumplida</em> con un valor, o <em>rechazada</em> con una razón (error). Cuando cualquiera de estas dos opciones sucede, los métodos asociados, encolados por el método <em>then</em> de la promesa, son llamados. (Si la promesa ya ha sido cumplida o rechazada en el momento que es anexado su correspondiente manejador, el manejador será llamado, de tal manera que no exista una condición de carrera entre la operación asíncrona siendo completada y los manejadores siendo anexados)</p>

<p>Como los métodos <code>{{jsxref("Promise.then", "Promise.prototype.then()")}}</code> y <code>{{jsxref("Promise.catch", "Promise.prototype.catch()")}}</code> retornan promesas, éstas pueden ser encadenadas.</p>

<p><img alt="" src="https://mdn.mozillademos.org/files/8633/promises.png"></p>

<div class="note">
<p><strong>No confundir con:</strong> Varios lenguajes tienen mecanismos para evaluar perezosamente y postergar una computación, a los que también les llaman "promesas" - p.ej.: Scheme. Las promesas en JavaScript representan procesos que ya están sucediendo, y pueden ser encadenados con funciones callback. Si lo que se busca es evaluar perezosamente una expresión, se debe considerar la función <a href="/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions">flecha </a> (arrow function) sin argumentos: <code>f = () =&gt; <em>expresión</em></code> para crear la expresión evaluada perezosamente, y <code>f()</code> para evaluar.</p>
</div>

<div class="note" id="settledNote">
<p><strong>Nota</strong>: Una promesa se dice que está <em>determinada (settled)</em> si se ha cumplido o si se ha rechazado, pero no está pendiente. Con promesas también se usa el término <em>resuelta</em> — esto significa que la promesa está determinada, o que se encuentra bloqueada dentro de una cadena de promesas. <a href="https://github.com/domenic/promises-unwrapping/blob/master/docs/states-and-fates.md">States and fates</a> de Domenic Denicola contiene mas detalles sobre la terminología de las promesas.</p>
</div>

<h2 id="Propiedades">Propiedades</h2>

<dl>
 <dt><code>Promise.length</code></dt>
 <dd>Propiedad longitud cuyo valor es siempre 1 (numero de argumentos del constructor).</dd>
 <dt>{{jsxref("Promise.prototype")}}</dt>
 <dd>Representa el prototipo del constructor <code>Promise</code>.</dd>
</dl>

<h2 id="Métodos">Métodos</h2>

<dl>
 <dt>{{jsxref("Promise.all", "Promise.all(iterable)")}}</dt>
 <dd>Devuelve una de dos promesas: una que se cumple cuando todas las promesas en el argumento iterable han sido cumplidas, o una que se rechaza tan pronto como una de las promesas del argumento iterable es rechazada. Si la promesa retornada es cumplida, lo hace con un arreglo de los valores de las promesas cumplidas en el mismo orden definido en el iterable. Si la promesa retornada es rechazada, es rechazada con la razón de la primera promesa rechazada en el iterable. Este método puede ser útil para agregar resultados de múltiples promesas</dd>
 <dt>{{jsxref("Promise.race", "Promise.race(iterable)")}}</dt>
 <dd>Devuelve una promesa que se cumple o rechaza tan pronto como una de las promesas del iterable se cumple o rechaza, con el valor o razón de esa promesa.</dd>
</dl>

<dl>
 <dt>{{jsxref("Promise.reject", "Promise.reject(reason)")}}</dt>
 <dd>Devuelve un objeto <code>Promise</code> que es rechazado con la razón dada.</dd>
</dl>

<dl>
 <dt>{{jsxref("Promise.resolve", "Promise.resolve(value)")}}</dt>
 <dd>Devuelve un objeto <code>Promise</code> que es resuelto con el valor dado. Si el valor es un <em>thenable</em> (p.ej. tiene un método <code>then</code>), la promesa devuelta "seguirá" este thenable, adoptando su eventual estado; de lo contrario la promesa devuelta será cumplida con el valor. Generalmente, si se quiere saber si un valor es una promesa o no, se podría usar - {{jsxref("Promise.resolve", "Promise.resolve(value)")}} y trabajar con el valor devuelto como una promesa.</dd>
</dl>

<h2 id="Prototipo_Promise">Prototipo <code>Promise</code></h2>

<h3 id="Propiedades_2">Propiedades</h3>

<p>{{page('en-US/Web/JavaScript/Reference/Global_Objects/Promise/prototype','Properties')}}</p>

<h3 id="Métodos_2">Métodos</h3>

<p>{{page('en-US/Web/JavaScript/Reference/Global_Objects/Promise/prototype','Methods')}}</p>

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

<h3 id="Súper_simple_¡10_líneas!">Súper simple (¡10 líneas!)</h3>

<pre class="brush: js notranslate"><code>let miPrimeraPromise = new Promise((resolve, reject) =&gt; {
  // Llamamos a resolve(...) cuando lo que estabamos haciendo finaliza con éxito, y reject(...) cuando falla.
  // En este ejemplo, usamos setTimeout(...) para simular código asíncrono.
  // En la vida real, probablemente uses algo como XHR o una API HTML5.
  setTimeout(function(){
    resolve("¡Éxito!"); // ¡Todo salió bien!
  }, 250);
});

miPrimeraPromise.then((successMessage) =&gt; {
  // succesMessage es lo que sea que pasamos en la función resolve(...) de arriba.
  // No tiene por qué ser un string, pero si solo es un mensaje de éxito, probablemente lo sea.
  console.log("¡Sí! " + successMessage);
});</code></pre>

<h3 id="Creando_una_Promise">Creando una Promise</h3>

<p>Este pequeño ejemplo muestra el mecanismo de una <code>Promise</code>. El método <code>testPromise()</code> se llama cada vez que se pulsa el {{HTMLElement("button")}}. Esto crea una promesa que se cumplirá, aplicando {{domxref("window.setTimeout()")}}, al contador de la promesa (partiendo desde 1) aleatoriamente cada 1-3 segundos. El constructor de la Promise() es usado para crear dicha promesa.</p>

<p>El cumplimiento de la promesa simplemente se registra, a través de una llamada de retorno al cumplirse utilizando {{jsxref("Promise.prototype.then()","p1.then()")}}. A los pocos registros muestra cómo la parte síncrona del método se desacopla de la finalización asíncrona de la promesa.</p>

<pre class="brush: js notranslate">'use strict';
var promiseCount = 0;

function testPromise() {
  var thisPromiseCount = ++promiseCount;

  var log = document.getElementById('log');
  log.insertAdjacentHTML('beforeend', thisPromiseCount +
    ') Comenzó (&lt;small&gt;Comenzó el código sincrónico&lt;/small&gt;)&lt;br/&gt;');

  // Hacemos una promesa: prometemos un contador numérico de esta promesa,
  // empezando por 1 (después de esperar 3s)
  var p1 = new Promise(
    // La función resolvedora es llamada con la
    // habilidad de resolver o rechazar la promesa
    function(resolve, reject) {
      log.insertAdjacentHTML('beforeend', thisPromiseCount +
        ') Comenzó la promesa (&lt;small&gt;Código asíncrono comenzó&lt;/small&gt;)&lt;br/&gt;');

      // Esto es solo un ejemplo para crear asincronismo
      window.setTimeout(
        function() {
          // ¡Cumplimos la promesa!
          resolve(thisPromiseCount);
        }, Math.random() * 2000 + 1000);
    }
  );

  // Definimos qué hacer cuando la promesa es resuelta/cumplida con la llamada
  // al método then(). La llamada al método catch() define qué hacer si
  // la promesa es rechazada
  p1.then(
    // Registrar el valor de la promesa cumplida
    function(val) {
      log.insertAdjacentHTML('beforeend', val +
        ') Promesa cumplida (&lt;small&gt;Código asíncrono terminado.&lt;/small&gt;)&lt;br/&gt;');
    })
  .catch(
    // Registrar la razón del rechazo
    function(reason) {
      console.log('Manejar promesa rechazada ('+reason+') aquí.');
    });

  log.insertAdjacentHTML('beforeend', thisPromiseCount +
    ') Promesa hecha (&lt;small&gt;Código síncrono terminado. &lt;/small&gt;)&lt;br/&gt;');
}
</pre>

<pre class="brush:js hidden notranslate">if ("Promise" in window) {
  var btn = document.getElementById("btn");
  btn.addEventListener("click",testPromise);
} else {
  log = document.getElementById('log');
  log.innerHTML = "El ejemplo en vivo no está disponible ya que tu navegador no soporta la interfaz &lt;code&gt;Promise&lt;code&gt;.";
}
</pre>

<p>Este ejemplo es ejecutado cuando pulsas el botón. Necesitas un navegador que soporte <code>Promise</code>. Al pulsar el botón varias veces en un período corto de tiempo, verás las diferentes promesas siendo cumplidas una tras otra.</p>

<p>{{EmbedLiveSample("Creando_una_Promise", "500", "200")}}</p>

<h2 id="Cargando_una_imagen_con_XHR">Cargando una imagen con XHR</h2>

<p>Otro ejemplo sencillo utilizando <code>Promise</code> y <code><a href="/en-US/docs/Web/API/XMLHttpRequest">XMLHttpRequest</a></code> para cargar una imagen está disponible en el repositorio <a href="https://github.com/mdn/js-examples/tree/master/promises-test">js-examples</a> de MDN en GitHub. También puedes <a href="https://mdn.github.io/js-examples/promises-test/">verlo en acción</a>. Cada paso está comentado y te permite seguir de cerca la arquitectura detrás de las Promesas y XHR.</p>

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

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Specification</th>
   <th scope="col">Status</th>
   <th scope="col">Comment</th>
  </tr>
  <tr>
   <td>{{SpecName('ES2015', '#sec-promise-objects', 'Promise')}}</td>
   <td>{{Spec2('ES2015')}}</td>
   <td>Initial definition in an ECMA standard.</td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-promise-objects', 'Promise')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td></td>
  </tr>
 </tbody>
</table>

<h2 id="Compatibilidad_de_navegadores">Compatibilidad de navegadores</h2>

<p class="hidden">To contribute to this compatibility data, please write a pull request against this file: <a href="https://github.com/mdn/browser-compat-data/blob/master/javascript/promise.json">https://github.com/mdn/browser-compat-data/blob/master/javascript/promise.json</a>.</p>

<p>{{Compat("javascript/promise")}}</p>

<h2 id="Ver_también">Ver también</h2>

<ul>
 <li><a href="http://promisesaplus.com/">Promises/A+ specification</a></li>
 <li><a href="https://medium.com/@ramsunvtech/promises-of-promise-part-1-53f769245a53">Venkatraman.R - JS Promise (Part 1, Basics)</a></li>
 <li><a href="https://medium.com/@ramsunvtech/js-promise-part-2-q-js-when-js-and-rsvp-js-af596232525c#.dzlqh6ski">Venkatraman.R - JS Promise (Part 2 - Using Q.js, When.js and RSVP.js)</a></li>
 <li><a href="http://www.html5rocks.com/en/tutorials/es6/promises/">Jake Archibald: JavaScript Promises: There and Back Again</a></li>
 <li><a href="http://de.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript">Domenic Denicola: Callbacks, Promises, and Coroutines – Asynchronous Programming Patterns in JavaScript</a></li>
 <li><a href="http://www.mattgreer.org/articles/promises-in-wicked-detail/">Matt Greer: JavaScript Promises ... In Wicked Detail</a></li>
 <li><a href="https://www.promisejs.org/">Forbes Lindesay: promisejs.org</a></li>
 <li><a href="http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html">Nolan Lawson: We have a problem with promises — Common mistakes with promises</a></li>
 <li><a href="https://github.com/jakearchibald/es6-promise/">Promise polyfill</a></li>
 <li><a href="https://www.udacity.com/course/javascript-promises--ud898">Udacity: JavaScript Promises</a></li>
</ul>