Promise

This is a new technology, part of the ECMAScript 2015 (ES6) standard.
This technology's specification has been finalized, but check the compatibility table for usage and implementation status in various browsers.

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(executor);
new Promise(function(resolve, reject) { ... });

Parametri

executor
Oggetto funzione con due argomenti resolve e reject. Il primo argomento soddisfa la promise, il secondo argomento la respinge. Possiamo richiamare queste funzioni nel momento in cui la nostra operazione é completata.

Descrizione

Una Promise rappresenta un proxy per un valore non necessariamente noto quando la promise è stato creato. Essa permette di associare dei handler (gestori) alla risposta di una azione asincrona, che può concretizzarsi in un eventuale valore di successo o nelle motivazioni del fallimento. Ciò permette ai metodi asincroni di restituire valori alla stessa maniera dei metodi sincroni: invece del valore finale, il metodo asincrono restituisce una promessa di ottenere un valore in un certo momento nel futuro.

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, che 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.

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 iterable sono state risolte. Questo é utile per aggregare insieme il risultato di più promeses.
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 una motivazione data.
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 vuoi sapere se è una promise o no - Promise.resolve(value) invece e lavora con il valore restituisce come una 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).

Esempi

Creazione di una Promise

Questo piccolo esempio illustra il meccanismo di una Promise. Il metodo testPromise() viene chiamato ogni volta che il <button> é cliccato. Esso crea una promise che verrà risolta, usando window.setTimeout(), con la stringa "result" entro 3 secondi e non prima di 1 in modo casuale. Per la creazione della promise viene usato il costruttore Promise().

La risoluzione della promessa viene semplicemente loggata tramite una callback agganciata tramite p1.then(). Poche righe di log mostrano come la parte sincrona del metodo è disaccoppiata dal completamento asincrono della promise.

'use strict';
var promiseCount = 0;

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

    var log = document.getElementById('log');
    log.insertAdjacentHTML('beforeend', thisPromiseCount +
        ') Started (<small>Sync code started</small>)<br/>');

    // Facciamo una nuova "promessa": promettiamo la strings 'result'
    // (dopo aver aspettato 3s)
    var p1 = new Promise(
        // La funzione è chiamata con la capacità di risolvere o
        // rigettare la promessa
        function(resolve, reject) {
            log.insertAdjacentHTML('beforeend', thisPromiseCount +
                ') Promise started (<small>Async code started</small>)<br/>');
            // Questo è solo un esempio per creare l'asincronicità
            window.setTimeout(
                function() {
                    // Rispettiamo la promessa!
                    resolve(thisPromiseCount);
                }, Math.random() * 2000 + 1000);
        });

    // Definiamo cosa fare in caso di risoluzione della promise
    // ma potremmo chiamare questo metodo solo se la
    // promise è soddisfatta
    p1.then(
        // Scrivi un log con un messaggio e un valore
        function(val) {
            log.insertAdjacentHTML('beforeend', val +
                ') Promise fulfilled (<small>Async code terminated</small>)<br/>');
        })
    .catch(
        // Le promesse fallite ingnorano il metodo Promise.prototype.then(onFulfilled)
        function(reason) {
            console.log('Handle rejected promise ('+reason+') here.');
        });

    log.insertAdjacentHTML('beforeend', thisPromiseCount +
        ') Promise made (<small>Sync code terminated</small>)<br/>');
}

Questo esempio è eseguito al click sul bottone (hai bisogno di un browser che supporti lo standard Promise). Cliccando ripetutamente sul bottone in un tempo breve, è possibile vedere le varie promesse che vengono risolte una dopo l'altra.

Esempio con una XMLHttpRequest()

Creazione di una Promise

Questo esempio mostra l'implementazione di un metodo che usa una Promise per notificare il successo o il fallimento di una XMLHttpRequest.

'use strict';

// A-> la funzione $http è implementata in modo da seguire il pattern standard Adapter
function $http(url){
 
  // Piccolo esempio di oggetto
  var core = {

    // Metodo che realizza la chiamata ajax
    ajax : function (method, url, args) {

      // Creazione della promise
      var promise = new Promise( function (resolve, reject) {

        // Generazione di una XMLHttpRequest
        var client = new XMLHttpRequest();
        var uri = url;

        if (args && (method === 'POST' || method === 'PUT')) {
          uri += '?';
          var argcount = 0;
          for (var key in args) {
            if (args.hasOwnProperty(key)) {
              if (argcount++) {
                uri += '&';
              }
              uri += encodeURIComponent(key) + '=' + encodeURIComponent(args[key]);
            }
          }
        }

        client.open(method, uri);
        client.send();

        client.onload = function () {
          if (this.status == 200) {
            // Performa la funzione "resolve"
            // quando this.status è 200
           resolve(this.response);
          } else {
            // Performa la funzione "reject"
            // quando this.status è diverso da 200
            reject(this.statusText);
          }
        };
        client.onerror = function () {
          reject(this.statusText);
        };
      });

      // Restituisce la promise
      return promise;
    }
  };

  // Adapter pattern
  return {
    'get' : function(args) {
      return core.ajax('GET', url, args);
    },
    'post' : function(args) {
      return core.ajax('POST', url, args);
    },
    'put' : function(args) {
      return core.ajax('PUT', url, args);
    },
    'delete' : function(args) {
      return core.ajax('DELETE', url, args);
    }
  };
};
// End A

// B-> Qui si definisce la sua funzione e il suo payload
var mdnAPI = 'https://developer.mozilla.org/en-US/search.json';
var payload = {
  'topic' : 'js',
  'q'     : 'Promise'
};

var callback = {
  success : function(data){
     console.log(1, 'success', JSON.parse(data));
  },
  error : function(data){
     console.log(2, 'error', JSON.parse(data));
  }
};
// End B

// Esegue la chiamata al metodo 
$http(mdnAPI) 
  .get(payload) 
  .then(callback.success) 
  .catch(callback.error);

// Esegue la chiamata al metodo con un metodo alternativo (1)
// di risolvere il caso di fallimento 
$http(mdnAPI) 
  .get(payload) 
  .then(callback.success, callback.error);

// Esegue la chiamata al metodo con un metodo alternativo (2)
// di risolvere il caso di fallimento
$http(mdnAPI) 
  .get(payload) 
  .then(callback.success)
  .then(undefined, callback.error);

Loading an image with XHR

Un altro semplice esempio che usa una PromiseXMLHttpRequest per caricare un'immagine è presente nel repository repository GitHub promise-test di MDN.  È disponibile anche una demo. Ogni passaggio è commentato e consente di seguire da vicino il ciclo di vita della Promise e della 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.

Supporto dei browser

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari Edge
Basic support 32.0 29.0 (29.0) [1] No support 19 7.1 (Yes)
Feature Android Android Webview Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile Chrome for Android
Basic support No support (Yes) 29.0 (29.0) [1] No support No support 8 32.0

[1] Gecko 24 ha una implementazione sperimentale delle Promise, sotto il nome iniziale di Future. Questo nome è stato modificato in Promise in Gecko 25, ma disabilitato di default sotto il flag flag dom.promise.enabled. Bug 918806 ha abilitato le Promise di default in Gecko 29.

Vedi anche

Tag del documento e collaboratori

 Hanno collaborato alla realizzazione di questa pagina: kdex, marcofugaro, mrbabbs, teoli, pasqLisena, lysz210
 Ultima modifica di: kdex,