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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
|
---
title: Promise
slug: Web/JavaScript/Reference/Global_Objects/Promise
tags:
- ECMAScript 2015
- JavaScript
- Promise
- async
translation_of: Web/JavaScript/Reference/Global_Objects/Promise
---
<div>{{JSRef}}</div>
<p>Gli oggetti <strong><code>Promise</code></strong> sono usati per computazioni in differita e asincrone. Una <code>Promise</code> rappresenta un'operazione che non è ancora completata, ma lo sarà in futuro.</p>
<h2 id="Sintassi">Sintassi</h2>
<pre class="brush: js">new Promise(function(resolve, reject) { ... });</pre>
<h3 id="Parametri">Parametri</h3>
<dl>
<dt>executor</dt>
<dd>
<p>Una funzione che ha due argomenti: <code>resolve</code> e <code>reject</code>. Tale funzione viene chiamata immediatamente dall'implementazione della Promise, passando i due argomenti <code>resolve</code> e <code>reject,</code> che sono due funzioni. Le due funzioni <code>resolve</code> e <code>reject</code>, quando chiamate, risolvono o rigettano la promise. L'esecutore inizia del lavoro (solitamente asincrono), e, una volta completato, chiama <code>resolve</code> per risolvere la promise, o <code>reject</code> se c'è stato qualche errore. Se un errore viene sollevato nella funzione di esecuzione <code>(executor)</code> la promise viene rigettata.</p>
</dd>
</dl>
<h2 id="Descrizione">Descrizione</h2>
<p>Una <code><strong>Promise</strong></code> rappresenta un proxy per un valore non necessariamente noto quando la promise è stata creata. Consente di associare degli handlers con il successo o il fallimento di un'azione asincrona (e il "valore" in caso di successo, o la motivazione in caso di fallimento). Questo in pratica consente di utilizzare dei metodi asincroni di fatto come se fossero sincroni: la funzione che compie del lavoro asincrono non ritorna il valore di completamento ma ritorna una <em>promise</em>, tramite la quale si potrà ottenere il valore di completamento una volta che la promise sarà terminata.</p>
<p>Una <code>Promise</code> può presentarsi in uno dei seguenti stati:</p>
<ul>
<li><em>pending </em>(attesa): stato iniziale, né soddisfatto né respinto.</li>
<li><em>fulfilled </em>(soddisfatto): significa che l'operazione si è conclusa con sucesso.</li>
<li><em>rejected</em> (respinto): significa che l'operazione à fallita.</li>
</ul>
<p>Una promise in <em>pending</em> può evolvere sia in <em>fulfilled </em>con un valore, sia in <em>rejected</em> con una motivazione (errore). Quando accade una di queste situazioni, vengono chiamati gli handler associati che sono stati accodati dal metodo <code>then</code> della promise. (Se la promise è già stata soddisfatta o respinta quando viene agganciato l'handler, quest'ultimo verrà chiamato immediatamente, quindi non è necessario che gli handler vengano agganciati prima del completamento dell'operazione asincrona).</p>
<p><font face="Open Sans, Arial, sans-serif">Poichè i metodi </font><code>{{jsxref("Promise.then", "Promise.prototype.then")}}</code> e <code>{{jsxref("Promise.catch", "Promise.prototype.catch")}}</code> restituiscono delle promise, è possibile concatenarli tramite l'operazione di <em>composition</em>.</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/8633/promises.png"></p>
<div class="note">
<p><strong>Da non confondere con: </strong>molti altri linguaggi hanno meccanismi simili per la lazy evaluation ed il calcolo differito, che a loro volta vengono chiamati "promise" (es. Schemes). Le Promise in Javascript rappresentano un processo che è gia accaduto, che può essere concatenato con delle funzioni di callback. Se stai cercando di eseguire una lazy evaluation (valutazione non immediata) di un'espressione, considera l'utilizzo delle <a href="https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Functions_and_function_scope/Arrow_functions">arrow function</a> senza argomenti: <code>f = () => <em>expression</em></code> per creare un'espressione non valutata immediatamente (lazy-evaluated) ed usare <code>f()</code> per valutarla.</p>
</div>
<div class="note">
<p><strong>Nota</strong>: Si dice che una promise è "ferma" (<em>settled) </em>se è soddisfatta o respinta, ma non in <em>pending</em>. Si può parlare anche di promessa "risolta" (<em>resolved</em>) quando la promise è ferma o è bloccata in una catena di promise. <a href="https://github.com/domenic/promises-unwrapping/blob/master/docs/states-and-fates.md">States and fates</a> di Domenic Denicola contiene maggiori dettagli sulla terminologia riguardo le promise.</p>
</div>
<h2 id="Proprietà">Proprietà</h2>
<dl>
<dt><code>Promise.length</code></dt>
<dd>La proprietà length (lunghezza) ha come valore 1 (numero di argomenti del costruttore).</dd>
<dt>{{jsxref("Promise.prototype")}}</dt>
<dd>Rappresenta il prototype per il costruttore della <code>Promise</code>.</dd>
</dl>
<h2 id="Metodi">Metodi</h2>
<dl>
<dt>{{jsxref("Promise.all", "Promise.all(iterable)")}}</dt>
<dd>Ritorna una promise che si risolve quando tutte le promises dell'argomento iterabile sono state risolte. Oppure, viene rigettato appena una promise dell'argomento di tipo <code>Iterable</code> viene rigettato. Se tutto va a buon fine, la promise viene completata con un array contenente i valori di completamento di ciascuna promise dell'iterable, nello stesso ordine di quello dell'iterable. In caso fallisca (cioè appena una prima promise dell'iterable fallisce), Promise.all viene rigettato con la ragione (errore) della prima promise che ha fallito. Questo è utile per aggregare insieme il risultato di più promises.</dd>
<dt>{{jsxref("Promise.race", "Promise.race(iterable)")}}</dt>
<dd>Restituisce una promise che si risolve o respinge, non appena una delle promises dell'iterable si risolve o respinge, con il valore o la motivazione da quella promise.</dd>
</dl>
<dl>
<dt>{{jsxref("Promise.reject", "Promise.reject(reason)")}}</dt>
<dd>Restituisce un oggetto <code>Promise</code> che è respinta con la data motivazione.</dd>
</dl>
<dl>
<dt>{{jsxref("Promise.resolve", "Promise.resolve(value)")}}</dt>
<dd>Restituise un oggetto <code>Promise</code> che è risolto con il valore dato. Se il valore é un thenable (es. ha un metodo <code>then</code>), la promise restituita "seguirà" quel thenable, usando il suo stato; altirmenti la promise restituita sarà soddisfatta con il valore. Generalmente, se non sei sicuro che un valore sia di tipo Promise usa {{jsxref("Promise.resolve", "Promise.resolve(value)")}} e lavora con il valore restituito dalla promise.</dd>
</dl>
<h2 id="Promise_prototype">Promise prototype</h2>
<h3 id="Proprietà_2">Proprietà</h3>
<p>{{page('en-US/Web/JavaScript/Reference/Global_Objects/Promise/prototype','Properties')}}</p>
<h3 id="Metodi_2">Metodi</h3>
<p>{{page('en-US/Web/JavaScript/Reference/Global_Objects/Promise/prototype','Methods')}}</p>
<h2 id="Creazione_di_una_Promise">Creazione di una Promise</h2>
<p>Un oggetto di tipo <code>Promise</code>, viene creato con la keyowrd <code>new</code> ed il suo costruttore. Questo costruttore accetta come argomento una funzione, chiamata "<code>funzione esecutore (executor function)</code>". Questa funzione accetta altre due funzioni come parametri. La prima (<code>resolve</code>) viene eseguita in modo asincrono quando l'operazione viene eseguita con successo e restituisce il risultato dell'operazione come valore. La seconda (<code>reject</code>) viene eseguita nel caso in cui l'operazione fallisca e restituisce il motivo per cui l'operazione non è stata eseguita: generalmente un oggetto di tipo <code>Error</code></p>
<pre class="brush: js" dir="rtl">const myFirstPromise = new Promise((resolve, reject) => {
// esegue qualcosa di asincrono che eventualmente chiama:
//
resolve(someValue); // fulfilled
// oppure
reject("motivo del fallimento"); // rejected
});</pre>
<p>Per creare una funzione con il comportamento di Promise, semplicemente restituisci una promise</p>
<pre class="brush: js">function myAsyncFunction(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = () => resolve(xhr.responseText);
xhr.onerror = () => reject(xhr.statusText);
xhr.send();
});
}</pre>
<h2 id="Esempi">Esempi</h2>
<h3 id="Esempio_semplice">Esempio semplice</h3>
<pre class="brush: js">let myFirstPromise = new Promise((resolve, reject) => {
// Chiamiamo resolve(...) quando viene eseguito correttamente, e reject(...) quando fallisce.
// In questo esempio viene utilizzato setTimeout(...) per simulare un'operazione asincrona.
// Nella realtà probabilmente utilizzerai qualcosa del tipo XHR o HTML5 API.
setTimeout(function(){
resolve("Success!"); // È andato tutto perfettamente!
}, 250);
});
myFirstPromise.then((successMessage) => {
// successMessage viene passato alla funzione resolve(...) .
// Non deve essere necessariamente una stringa, ma nel caso sia solo un messaggio probabilmemte lo sarà.
console.log("Yay! " + successMessage);
});</pre>
<h3 id="Esempio_avanzato">Esempio avanzato</h3>
<pre class="brush: html"><button id="btn">Make a promise!</button>
<div id="log"></div></pre>
<p>Questo piccolo esempio mostra il meccanismo delle <code>Promise</code>. Il metodo <code>testPromise()</code> viene richiamato ogni volta che il {{HTMLElement("button")}} viene cliccato. Crea una promise che viene risolta correttamente (fulfilled), utilizzando {{domxref("window.setTimeout()")}} che incrementa il contatore ogni 1-3 secondi (random). Il costruttore <code>Promise</code> viene utilizzato per creare la promise.</p>
<p>La risoluzione della promise viene semplicemente loggata tramite una funzione di callback <code>fulfill</code> {{jsxref("Promise.prototype.then()","p1.then()")}}. Una serie di log mostrano che il comportamento sincrono del metodo è disaccoppiato rispetto all'esecuzione asincrona della promise.</p>
<pre class="brush: js">'use strict';
var promiseCount = 0;
function testPromise() {
let thisPromiseCount = ++promiseCount;
let log = document.getElementById('log');
log.insertAdjacentHTML('beforeend', thisPromiseCount +
') Started (<small>Sync code started</small>)<br/>');
// We make a new promise: we promise a numeric count of this promise, starting from 1 (after waiting 3s)
let p1 = new Promise(
// The resolver function is called with the ability to resolve or
// reject the promise
(resolve, reject) => {
log.insertAdjacentHTML('beforeend', thisPromiseCount +
') Promise started (<small>Async code started</small>)<br/>');
// This is only an example to create asynchronism
window.setTimeout(
function() {
// We fulfill the promise !
resolve(thisPromiseCount);
}, Math.random() * 2000 + 1000);
}
);
// We define what to do when the promise is resolved with the then() call,
// and what to do when the promise is rejected with the catch() call
p1.then(
// Log the fulfillment value
function(val) {
log.insertAdjacentHTML('beforeend', val +
') Promise fulfilled (<small>Async code terminated</small>)<br/>');
}).catch(
// Log the rejection reason
(reason) => {
console.log('Handle rejected promise ('+reason+') here.');
});
log.insertAdjacentHTML('beforeend', thisPromiseCount +
') Promise made (<small>Sync code terminated</small>)<br/>');
}
if ("Promise" in window) {
let btn = document.getElementById("btn");
btn.addEventListener("click",testPromise);
} else {
log = document.getElementById('log');
log.innerHTML = "Live example not available as your browser doesn't support the <code>Promise<code> interface.";
}</pre>
<p>In questo esempio si comincia cliccando il bottone. Per testare necessiti di un browser che supporta le <code>Promise</code>. Cliccando il bottone diverse volte in un lasso di tempo breve vedrai che le funzioni verranno risolte una dopo l'altra.</p>
<h2 id="Caricare_un'immagine_con_XHR">Caricare un'immagine con XHR</h2>
<p>Un'altro semplice esempio che utilizza le Promise e <a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest">XMLHttpRequest</a> mostra come caricare un'immagine è disponibile sul <a href="https://github.com/mdn/js-examples/tree/master/promises-test">repository</a> di MDN su Github. Puoi inoltre vederla in azione. Ogni azione è commentata e puoi seguire passo-passo come viene creata la Promise e gestita tramite XHR.</p>
<h2 id="Specifiche">Specifiche</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Specifica</th>
<th scope="col">Stato</th>
<th scope="col">Commento</th>
</tr>
<tr>
<td>{{SpecName('ES2015', '#sec-promise-objects', 'Promise')}}</td>
<td>{{Spec2('ES2015')}}</td>
<td>
<p>Prima definizione in uno standard ECMA.</p>
</td>
</tr>
<tr>
<td>{{SpecName('ESDraft', '#sec-promise-objects', 'Promise')}}</td>
<td>{{Spec2('ESDraft')}}</td>
<td>
<p> </p>
</td>
</tr>
</tbody>
</table>
<h2 id="Supporto_dei_browser">Supporto dei browser</h2>
<p>{{Compat("javascript.builtins.Promise")}}</p>
<h2 id="Vedi_anche">Vedi anche</h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises">Using promises</a></li>
<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="https://tech.io/playgrounds/11107/tools-for-promises-unittesting/introduction">Venkatraman.R - Tools for Promises Unit Testing</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="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>
<li> </li>
</ul>
|