Comprensione delle promesse in Node.js


147

Da quello che ho capito ci sono tre modi per chiamare il codice asincrono:

  1. Eventi, ad es request.on("event", callback);
  2. Richiamate, ad es fs.open(path, flags, mode, callback);
  3. promesse

Ho trovato la libreria promessa nodo ma non la capisco.

Qualcuno potrebbe spiegare quali sono le promesse e perché dovrei usarle?

Inoltre, perché è stato rimosso da Node.js?


Questo articolo lo spiega piuttosto bene. Quando si tratta di un'implementazione utilizzabile in node.js, dai un'occhiata a Futures
Sean Kinsey,

Ecco una grande serie che ho usato per creare la mia classe di promesse: Let's Make a Framework: Promises Ecco il video su jQuery Deferred: blog.bigbinary.com/2011/09/03/jquery-deferred.html
Tom Winter

Risposte:


91

Le promesse in node.js hanno promesso di fare un po 'di lavoro e quindi hanno avuto callback separati che sarebbero stati eseguiti per successo e fallimento, nonché per la gestione dei timeout. Un altro modo di pensare alle promesse in node.js era che erano emettitori che potevano emettere solo due eventi: successo ed errore.

La cosa bella delle promesse è che puoi combinarle in catene di dipendenze (fai Promessa C solo quando Promessa A e Promessa B sono complete).

Rimuovendoli dal core node.js, ha creato la possibilità di creare moduli con diverse implementazioni di promesse che possono stare in cima al core. Alcuni di questi sono promessa di nodo e futuro .


10
@weng No non lo è.
Ivo Wetzel,

98

Poiché questa domanda ha ancora molti punti di vista (come la mia), ho voluto sottolineare che:

  1. la promessa del nodo mi sembra piuttosto morta (l'ultimo commit è stato effettuato circa 1 anno fa) e non contiene quasi alcun test.
  2. Il modulo sui futures mi sembra molto gonfio ed è mal documentato (e penso che le convenzioni di denominazione siano semplicemente cattive)
  3. Il modo migliore per procedere sembra essere il framework q , che è sia attivo che ben documentato.

9
Dai un'occhiata anche a questo github.com/medikoo/deferred , Q è uno dei primi ed è sicuramente fonte di ispirazione per molte implementazioni che sono apparse in seguito, ma sfortunatamente è molto lento e troppo "teorico" in alcune parti, non suona bene con alcune scenari del mondo reale
Mariusz Nowak,

Guarderei questo video sulle promesse di uno dei creatori di RSVP.js youtube.com/…
eseguito l'

23
Aggiornamento 2014 - bluebird è di gran lunga il più veloce e quello con le migliori capacità di debug oggi.
Benjamin Gruenbaum,

19

Una promessa è una "cosa" che rappresenta i risultati "eventuali" di un'operazione per così dire. Il punto da notare qui è che, estrae i dettagli di quando succede qualcosa e ti permette di concentrarti su ciò che dovrebbe accadere dopo che qualcosa accade. Ciò si tradurrà in un codice pulito e gestibile in cui invece di avere un callback all'interno di un callback all'interno di un callback, il tuo codice sarà in qualche modo simile a:

 var request = new Promise(function(resolve, reject) {
   //do an ajax call here. or a database request or whatever.
   //depending on its results, either call resolve(value) or reject(error)
   //where value is the thing which the operation's successful execution returns and
   //error is the thing which the operation's failure returns.
 });

 request.then(function successHandler(result) {
   //do something with the result
 }, function failureHandler(error) {
  //handle
 });

La specifica delle promesse afferma che una promessa

then

Il metodo dovrebbe restituire una nuova promessa che viene adempiuta al termine del callback successHandler o failHandler indicato. Ciò significa che è possibile concatenare le promesse quando si dispone di una serie di attività asincrone che devono essere eseguite ed è garantito che il sequenziamento delle operazioni sia garantito proprio come se si fossero utilizzati i callback. Quindi, invece di passare un callback all'interno di un callback all'interno di un callback, il codice con promesse concatenate assomiglia a:

var doStuff = firstAsyncFunction(url) {
                return new Promise(function(resolve, reject) {
                       $.ajax({
                        url: url,
                        success: function(data) {
                            resolve(data);
                        },
                        error: function(err) {
                             reject(err); 
                        } 
                  });
               };
doStuff
  .then(secondAsyncFunction) //returns a promise
  .then(thirdAsyncFunction); //returns a promise

Per saperne di più sulle promesse e sul perché sono fantastiche, consulta il blog di Domenic: http://domenic.me/2012/10/14/youre-missing-the-point-of-promises/


12

Questo nuovo tutorial su Promesse dall'autore di PouchDB è probabilmente il migliore che abbia mai visto. Copre saggiamente i classici errori da principiante mostrandoti i modelli di utilizzo corretti e anche alcuni anti-schemi che sono ancora comunemente usati - anche in altri tutorial !!

Godere!

PS Non ho risposto ad altre parti di questa domanda in quanto sono state ben coperte da altri.


Le mie uniche scuse per questo sono costringerti a leggere l'umorismo alla fine dell'errore avanzato n. 4.
Tony O'Hagan,

In effetti, il codice nell'esercitazione che sostengono di essere un antipattern ha bisogno dell'annidamento per il ciclo e la condizione e non può essere facilmente appiattito come suggeriscono.
Bergi,

L'errore avanzato n. 4 può anche essere risolto utilizzando un numero molto maggiore di approcci diversi, vedi Come posso accedere ai risultati delle promesse precedenti in una catena .then ()? (il modello di chiusura che suggeriscono non sembra essere molto popolare).
Bergi,

Penso che questa risposta solo link dovrebbe essere meglio un commento. Inserisci qui almeno i punti principali di quell'articolo nella tua risposta.
Bergi,

7

Mike Taulty ha una serie di video , ognuno dei quali dura meno di dieci minuti, che descrivono come funziona la libreria WinJS Promise.

Questi video sono piuttosto istruttivi e Mike riesce a mostrare la potenza dell'API Promise con alcuni esempi di codice ben scelti.

var twitterUrl = "http://search.twitter.com/search.json?q=windows";
var promise = WinJS.xhr({ url: twitterUrl });

 promise = promise.then(
     function (xhr) {
     },
     function (xhr) {
         // handle error
     });

Il trattamento di come vengono trattate le eccezioni è particolarmente buono.

Nonostante i riferimenti di WinJs, questa è una serie di video di interesse generale, poiché l'API Promise è sostanzialmente simile in tutte le sue implementazioni.

RSVP è un'implementazione leggera di Promise che supera la suite di test Promise / A +. Mi piace abbastanza l'API, perché è simile nello stile all'interfaccia WinJS.

Aggiornamento aprile 2014

Per inciso, la libreria WinJS è ora open source .


1
+1. Questo è il primo esempio che ho visto che ha senso per me ed è intuitivo da usare. In qualche modo il mio cervello non è in grado di analizzare tutto deferredse resolvee deferred.promise.thene predefinire promiseActionsnella popolare documentazione della libreria Q. Qualche possibilità di sapere qualcosa di così semplice per Node.js ?
Redsandro,

1
@noel grazie per aver condiviso il link sopra, è un'ottima serie introduttiva per le promesse e sono d'accordo che le specifiche di WinJS sono irrilevanti in quanto l'approccio / argomento generale è universale.
ArcSeldon,

Bell'esempio Inoltre ho corretto il tuo primo link che era morto
stonedauwg il

5

Un altro vantaggio delle promesse è che la gestione degli errori e il lancio e la cattura delle eccezioni sono molto meglio che provare a gestirlo con i callback.

La libreria bluebird implementa le promesse e ti dà grandi tracce dello stack, è molto veloce e avverte di errori non rilevati. Inoltre è più veloce e utilizza meno memoria rispetto alle altre librerie promesse, secondo http://bluebirdjs.com/docs/benchmarks.html


4

Che cos'è esattamente una promessa?

Una promessa è semplicemente un oggetto che rappresenta il risultato di un'operazione asincrona. Una promessa può essere in uno dei seguenti 3 stati:

pending :: Questo è lo stato iniziale, significa che la promessa non è stata rispettata né respinta.

adempiuto :: Ciò significa che la promessa è stata adempiuta, significa che il valore rappresentato dalla promessa è pronto per essere utilizzato.

respinto :: Ciò significa che le operazioni sono fallite e quindi non possono mantenere la promessa. Oltre agli stati, ci sono tre entità importanti associate alle promesse che dobbiamo davvero capire

  1. funzione esecutore :: funzione esecutore definisce l'operazione asincrona che deve essere eseguita e il cui risultato è rappresentato dalla promessa. Inizia l'esecuzione non appena viene inizializzato l'oggetto promessa.

  2. resol :: resolve è un parametro passato alla funzione esecutore e, nel caso in cui l'esecutore funzioni correttamente, questa risoluzione viene chiamata passando il risultato.

  3. reject :: reject è un altro parametro passato alla funzione di esecuzione e viene utilizzato quando la funzione di esecuzione ha esito negativo. Il motivo dell'errore può essere passato al rifiuto.

Quindi ogni volta che creiamo un oggetto promessa, dobbiamo fornire Executor, Resolve e Reject.

Riferimento :: Promesse


0

Di recente ho anche cercato promesse in node.js. Ad oggi il when.js sembra essere la strada da percorrere a causa della sua velocità e dell'utilizzo delle risorse, ma la documentazione su q.js mi ha dato una comprensione molto migliore. Quindi usa when.js ma i documenti q.js per capire l'argomento.

Dal readme q.js su github:

Se una funzione non può restituire un valore o generare un'eccezione senza bloccare, può invece restituire una promessa. Una promessa è un oggetto che rappresenta il valore restituito o l'eccezione generata che la funzione può eventualmente fornire. Una promessa può anche essere utilizzata come proxy per un oggetto remoto per superare la latenza.


0

L'oggetto Promise rappresenta il completamento o il fallimento di un'operazione asincrona.

Quindi, al fine di attuare una promessa, sono necessarie due parti: -

1. Creazione di promesse:

Il costruttore promessa accetta una funzione chiamata esecutore con risoluzione e rifiuto di 2 parametri.

function example(){
   return new Promise (function(resolve , reject){   //return promise object
      if(success){
         resolve('success');  //onFullfiled
      }else{
         reject('error');     //onRejected
      }
   })
}

2. Promessa di gestione:

L'oggetto Promise ha 3 metodi per gestire gli oggetti Promessa: -

1.Promise.prototype.catch (onRejected)

2.Promise.prototype.then (onFullfiled)

3.Promise.prototype.finally (onFullfiled, onRejected)

example.then((data) =>{
  //handles resolved data
  console.log(data); //prints success     
}).catch((err) => {
  //handles rejected error 
  console.log(err);  //prints error
})
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.