Gli oggetti Promise sono usati per computazioni in differita e asincrone. Una Promise rappresenta un'operazione che non è ancora completata, ma lo sarà in futuro.

Sintassi

new Promise(function(resolve, reject) { ... });

Parametri

executor

Una funzione che ha due argomenti: resolve e reject.  Tale funzione viene chiamata immediatamente dall'implementazione della Promise, passando i due argomenti resolve e reject, che sono due funzioni. Le due funzioni resolve e reject, quando chiamate, risolvono o rigettano la promise. L'esecutore inizia del lavoro (solitamente asincrono), e, una volta completato, chiama resolve per risolvere la promise, o reject se c'è stato qualche errore. Se un errore viene sollevato nella funzione di esecuzione (executor) la promise viene rigettata.

Descrizione

Una Promise 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 promise, tramite la quale si potrà ottenere il valore di completamento una volta che la promise sarà terminata.

Una Promise può presentarsi in uno dei seguenti stati:

  • pending (attesa): stato iniziale, né soddisfatto né respinto.
  • fulfilled (soddisfatto): significa che l'operazione si è conclusa con sucesso.
  • rejected (respinto): significa che l'operazione à fallita.

Una promise in pending può evolvere sia in fulfilled con un valore, sia in rejected con una motivazione (errore). Quando accade una di queste situazioni, vengono chiamati gli handler associati che sono stati accodati dal metodo then 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).

Poichè i metodi Promise.prototype.then e Promise.prototype.catch restituiscono delle promise, è possibile concatenarli tramite l'operazione di composition.

Da non confondere con: 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 arrow function senza argomenti: f = () => expression per creare un'espressione non valutata immediatamente (lazy-evaluated) ed usare f() per valutarla.

Nota: Si dice che una promise è "ferma" (settled) se è soddisfatta o respinta, ma non in pending. Si può parlare anche di promessa "risolta" (resolved) quando la promise è ferma o è bloccata in una catena di promise. States and fates di Domenic Denicola contiene maggiori dettagli sulla terminologia riguardo le promise.

Proprietà

Promise.length
La proprietà length (lunghezza) ha come valore 1 (numero di argomenti del costruttore).
Promise.prototype
Rappresenta il prototype per il costruttore della Promise.

Metodi

Promise.all(iterable)
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 Iterable 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.
Promise.race(iterable)
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.
Promise.reject(reason)
Restituisce un oggetto Promise che è respinta con la data motivazione.
Promise.resolve(value)
Restituise un oggetto Promise che è risolto con il valore dato. Se il valore é un thenable (es. ha un metodo then), 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 Promise.resolve(value) e lavora con il valore restituito dalla promise.

Promise prototype

Proprietà

Promise.prototype.constructor
Returns the function that created an instance's prototype. This is the Promise function by default.

Metodi

Promise.prototype.catch(onRejected)
Appends a rejection handler callback to the promise, and returns a new promise resolving to the return value of the callback if it is called, or to its original fulfillment value if the promise is instead fulfilled.
Promise.prototype.then(onFulfilled, onRejected)
Appends fulfillment and rejection handlers to the promise, and returns a new promise resolving to the return value of the called handler, or to its original settled value if the promise was not handled (i.e. if the relevant handler onFulfilled or onRejected is not a function).
Promise.prototype.finally(onFinally)
Appends a handler to the promise, and returns a new promise which is resolved when the original promise is resolved. The handler is called when the promise is settled, whether fulfilled or rejected.

Creazione di una Promise

Un oggetto di tipo Promise, viene creato con la keyowrd new ed il suo costruttore. Questo costruttore accetta come argomento una funzione, chiamata "funzione esecutore (executor function)". Questa funzione accetta altre due funzioni come parametri. La prima (resolve) viene eseguita in modo asincrono quando l'operazione viene eseguita con successo e restituisce il risultato dell'operazione come valore. La seconda (reject) 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 Error

const myFirstPromise = new Promise((resolve, reject) => {
  // esegue qualcosa di asincrono che eventualmente chiama:
  //
     resolve(someValue); // fulfilled
  // oppure
     reject("motivo del fallimento"); // rejected
});

Per creare una funzione con il comportamento di Promise, semplicemente restituisci una promise

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();
  });
}

Esempi

Esempio semplice

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);
});

Esempio avanzato

<button id="btn">Make a promise!</button>
<div id="log"></div>

Questo piccolo esempio mostra il meccanismo delle Promise. Il metodo testPromise() viene richiamato ogni volta che il <button> viene cliccato. Crea una promise che viene risolta correttamente (fulfilled), utilizzando window.setTimeout() che incrementa il contatore ogni 1-3 secondi (random). Il costruttore Promise viene utilizzato per creare la promise.

La risoluzione della promise viene semplicemente loggata tramite una funzione di callback fulfill p1.then(). Una serie di log mostrano che il comportamento sincrono del metodo è disaccoppiato rispetto all'esecuzione asincrona della promise.

'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.";
}

In questo esempio si comincia cliccando il bottone. Per testare necessiti di un browser che supporta le Promise. Cliccando il bottone diverse volte in un lasso di tempo breve vedrai che le funzioni verranno risolte una dopo l'altra.

Caricare un'immagine con XHR

Un'altro semplice esempio che utilizza le Promise e XMLHttpRequest mostra come caricare un'immagine è disponibile sul repository 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.

Specifiche

Specifica Stato Commento
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Promise' in that specification.
Standard

Prima definizione in uno standard ECMA.

ECMAScript Latest Draft (ECMA-262)
The definition of 'Promise' in that specification.
Draft

 

Supporto dei browser

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidEdge MobileFirefox for AndroidOpera for AndroidSafari on iOSSamsung InternetNode.js
Basic supportChrome Full support 32Edge Full support YesFirefox Full support 29IE No support NoOpera Full support 19Safari Full support 8WebView Android Full support 4.4.3Chrome Android Full support 32Edge Mobile Full support YesFirefox Android Full support 29Opera Android Full support YesSafari iOS Full support 8Samsung Internet Android Full support Yesnodejs Full support 0.12
Promise() constructorChrome Full support 32Edge Full support YesFirefox Full support 29
Notes
Full support 29
Notes
Notes Constructor requires a new operator since version 37.
IE No support NoOpera Full support 19Safari Full support 8
Notes
Full support 8
Notes
Notes Constructor requires a new operator since version 10.
WebView Android Full support 4.4.3Chrome Android Full support 32Edge Mobile Full support YesFirefox Android Full support 29
Notes
Full support 29
Notes
Notes Constructor requires a new operator since version 37.
Opera Android Full support YesSafari iOS Full support 8
Notes
Full support 8
Notes
Notes Constructor requires a new operator since version 10.
Samsung Internet Android Full support Yesnodejs Full support 0.12
Notes
Full support 0.12
Notes
Notes Constructor requires a new operator since version 4.
allChrome Full support 32Edge Full support YesFirefox Full support 29IE No support NoOpera Full support 19Safari Full support 8WebView Android Full support 4.4.3Chrome Android Full support 32Edge Mobile Full support YesFirefox Android Full support 29Opera Android Full support YesSafari iOS Full support 8Samsung Internet Android Full support Yesnodejs Full support 0.12
prototypeChrome Full support 32Edge Full support YesFirefox Full support 29IE No support NoOpera Full support 19Safari Full support 8WebView Android Full support 4.4.3Chrome Android Full support 32Edge Mobile Full support YesFirefox Android Full support 29Opera Android Full support YesSafari iOS Full support 8Samsung Internet Android Full support Yesnodejs Full support 0.12
catchChrome Full support 32Edge Full support YesFirefox Full support 29IE No support NoOpera Full support 19Safari Full support 8WebView Android Full support 4.4.3Chrome Android Full support 32Edge Mobile Full support YesFirefox Android Full support 29Opera Android Full support YesSafari iOS Full support 8Samsung Internet Android Full support Yesnodejs Full support 0.12
finallyChrome Full support 63Edge Full support 18Firefox Full support 58IE No support NoOpera Full support 50Safari Full support 11.1WebView Android Full support 63Chrome Android Full support 63Edge Mobile No support NoFirefox Android Full support 58Opera Android Full support 50Safari iOS Full support 11.1Samsung Internet Android No support Nonodejs Full support 10.0.0
thenChrome Full support 32Edge Full support YesFirefox Full support 29IE No support NoOpera Full support 19Safari Full support 8WebView Android Full support 4.4.3Chrome Android Full support 32Edge Mobile Full support YesFirefox Android Full support 29Opera Android Full support YesSafari iOS Full support 8Samsung Internet Android Full support Yesnodejs Full support 0.12
raceChrome Full support 32Edge Full support YesFirefox Full support 29IE No support NoOpera Full support 19Safari Full support 8WebView Android Full support 4.4.3Chrome Android Full support 32Edge Mobile Full support YesFirefox Android Full support 29Opera Android Full support YesSafari iOS Full support 8Samsung Internet Android Full support Yesnodejs Full support 0.12
rejectChrome Full support 32Edge Full support YesFirefox Full support 29IE No support NoOpera Full support 19Safari Full support 8WebView Android Full support 4.4.3Chrome Android Full support 32Edge Mobile Full support YesFirefox Android Full support 29Opera Android Full support YesSafari iOS Full support 8Samsung Internet Android Full support Yesnodejs Full support 0.12
resolveChrome Full support 32Edge Full support YesFirefox Full support 29IE No support NoOpera Full support 19Safari Full support 8WebView Android Full support 4.4.3Chrome Android Full support 32Edge Mobile Full support YesFirefox Android Full support 29Opera Android Full support YesSafari iOS Full support 8Samsung Internet Android Full support Yesnodejs Full support 0.12

Legend

Full support  
Full support
No support  
No support
See implementation notes.
See implementation notes.

Vedi anche

Tag del documento e collaboratori

Hanno collaborato alla realizzazione di questa pagina: frappacchio, SphinxKnight, lorthirk, cipollafrancesco, AAllegro91, nbena, kdex, marcofugaro, mrbabbs, teoli, pasqLisena, lysz210
Ultima modifica di: frappacchio,