2013-01-02 20 views
50

Eventuali duplicati:
What are the differences between Deferred, Promise and Future in Javascript?Asynchronous JavaScript - callback vs differite/Promessa

Ultimamente sto facendo uno sforzo per migliorare la qualità delle mie applicazioni JavaScript.

Uno schema che ho adottato è quello di utilizzare un oggetto "contesto dati" separato per caricare i dati per la mia applicazione (in precedenza lo stavo facendo direttamente nei miei modelli di vista).

L'esempio seguente restituisce i dati che viene inizializzato sul client:

var mockData = (function($, undefined) { 

    var fruit = [ 
     "apple", 
     "orange", 
     "banana", 
     "pear" 
     ]; 

    var getFruit = function() { 
     return fruit; 
    }; 

    return { 
     getFruit: getFruit 
    } 
})(jQuery); 

Nella maggior parte dei casi saremo caricamento dei dati dal server in modo che non possiamo restituire una risposta immediata. Sembra che io abbia due opzioni per come gestiamo questo nella nostra API:

  1. Utilizzando un callback
  2. Restituzione di una promise.

In precedenza avevo sempre usato l'approccio di callback:

var getFruit = function(onFruitReady) { 
    onFruitReady(fruit); 
}; 

// ... 

var FruitModel = function(dataContext, $) { 
    return { 
     render: function() { 
      dataContext.getFruit(function(fruit) { 
       // do something with fruit 
      }); 
     } 
    }; 
}; 

Tuttavia, posso vedere come è possibile finire in un inferno di richiamata, in particolare per la costruzione di applicazioni JavaScript complesse.

Poi ho trovato il modello di progettazione Promises. Invece di richiedere al chiamante di fornire una richiamata, io invece restituire una "promessa" che si può osservare:

var getFruit = function() { 
    return $.Deferred().resolve(fruit).promise(); 
}; 

// ... 
dataContext.getFruit().then(function(fruit) { 
    // do something with fruit 
}); 

posso vedere evidenti vantaggi dell'utilizzo di questo modello, soprattutto perché posso wait su più oggetti anticipate che potrebbero essere molto utile quando si caricano i dati di inizializzazione per un'applicazione a singola pagina.

Tuttavia, sono desideroso di comprendere i pro e i contro di ciascun modello prima di iniziare a utilizzare la rabbia. Mi interessa anche se questa è la direzione in cui entrano le altre librerie. Sembra che sia il caso di jQuery.

Ecco un link per il violino che sto usando per il test.

+4

Beh buona notizia: le API Ajax jQuery * * già promesse di ritorno! – Pointy

+0

[Leggi il meccanismo qui.] (Http://api.jquery.com/jQuery.ajax/#jqXHR) – Pointy

+0

Sì, questo è il modo in cui mi sono imbattuto nel modello in quanto cercavo un modo per astrarre le mie chiamate Ajax. –

risposta

18

Le promesse si basano anche sui richiami dietro la scena, quindi non è davvero uno contro l'altro.

Il vantaggio dei callback è che sono facili da implementare con JavaScript semplice (ad esempio nelle chiamate Ajax).

Le promesse richiedono un livello di astrazione aggiuntivo, che in genere significa che ci si affida a una libreria (non è un problema nel tuo caso poiché stai già utilizzando jQuery). Sono perfetti quando gestisci più chiamate asincrone in parallelo.

+9

Si noti che a partire da marzo 2014, i browser hanno iniziato a implementare promesse native , quindi la mia affermazione vale solo per i polyfill. – Christophe

3

Dalla lettura del jQuery docs che @Pointy legato a, suona come la differenza è che l'API differito consente di specificare più di una funzione da chiamare quando la richiesta viene completata:

Come di jQuery 1.5 , l'errore (fallito), il successo (fatto) e il completamento (sempre, come da jQuery 1.6) i hook di callback sono le code gestite first-out, first-out. Ciò significa che è possibile assegnare più di un callback per ciascun hook. Vedere i metodi dell'oggetto differito, che sono implementati internamente per questi hook di callback $ .ajax().

Consulta anche: deferred.then()

+1

Non è che Deferreds/promises * consenta * di specificare più di una funzione da chiamare, a meno che lo facciano * più facilmente *. Le caratteristiche particolari sono che (a) le funzioni possono essere aggiunte (ad esempio '.done()' o '.fail()') in qualsiasi parte del codice, soggetto solo al fatto che Deferred/promise sia nell'ambito di scope, e (b) funzioni aggiunto dopo che un rinvio è stato risolto/respinto, sparerà immediatamente. Esponendo la sua utility interna '.Callbacks()', jQuery rende questo tipo di funzionalità * possibile * senza usare Deferred/promises, ma si prende il disturbo dal coding/debugging. –