2015-08-21 16 views
5

Quando dovrei usare quale? Quanto segue è lo stesso?Bluebird.JS Promessa: nuova promessa (funzione (risoluzione, rifiuto) {}) vs Promise.try (function() {})

nuova promessa() Esempio:

function multiRejectExample(){ 
    return new Promise(function (resolve, reject){ 
    if(statement){ 
     console.log('statement 1'); 
     reject(throw new Error('error')); 
    } 
    if(statement){ 
    console.log('statement 2'); 
    reject(throw new Error('error')); 
    } 
    }); 
} 

Promise.try() Esempio:

function tryExample(){ 
    return Promise.try(function(){ 
    if(statement){ 
     console.log('statement 1'); 
     throw new Error('error'); 
    } 
    if(statement){ 
    console.log('statement 2'); 
    throw new Error('error'); 
    } 
    }); 
} 
+0

collegato in modo approssimativo: [Promise.reject vs throw error] (http://stackoverflow.com/q/28703241/1048572). Non dovresti usare il costruttore 'new Promise' a meno che tu non stia facendo qualcosa in modo asincrono. L'approccio corretto qui sarebbe quello di restituire Promise.reject (...) (o usare 'Promise.try' /' Promise.method'). – Bergi

risposta

8

È possibile utilizzare la maggior parte sia in questo caso (con una differenza comportamento). Il primo è la funzionalità standard di promessa e funzionerà con qualsiasi libreria di promessa.

Promise.try() è una funzionalità specificatamente implementata dalla libreria Bluebird e non fa parte di alcun processo standard di cui sono a conoscenza.

Il motivo per utilizzare Promise.try() è se si dispone di una funzione che restituisce una promessa, ma il codice che genera tale promessa potrebbe anche causare un'eccezione sincrona. Dal momento che quell'eccezione non è all'interno di alcun gestore di promesse, avresti un mix di gestione degli errori. Alcuni percorsi di esecuzione del codice potrebbero causare la restituzione di una promessa che sarebbe risolta o rifiutata e altri percorsi di esecuzione del codice potrebbero generare un'eccezione. Per codificare questo in modo sicuro, dovresti entrambi rispondere alla promessa e mettere un blocco try/catch attorno al codice che diventa ingombrante.

Promise.try() è semplicemente un mezzo per rilevare automaticamente eventuali eccezioni e trasformarle in un rifiuto (simile a ciò che accade nei gestori .then()).

Nei due casi, Promise.try() non è vantaggioso in questo modo perché la richiamata new Promise() intercetta già eccezioni e le trasforma in rifiuti in modo che la funzionalità sia già stata eseguita per voi. Si può vedere che ha dimostrato qui: http://jsfiddle.net/jfriend00/wLov9844/

Il doc Bluebird offre questo esempio che mostra il beneficio più chiaramente:

function getUserById(id) { 
    return Promise.try(function() { 
     if (typeof id !== "number") { 
      // Courtesy of Promise.try() this exception will be turned 
      // into a returned promise that is rejected with the 
      // exception as the reason 
      throw new Error("id must be a number"); 
     } 
     return db.getUserById(id); 
    }); 
} 

getUserById().then(successFn, errFn); 

L'uso di Promise.try() qui fa in modo che getUserById() sarà sempre tornare una promessa, anche se il il codice all'interno di quel metodo genera un'eccezione in modo sincrono. Questo semplifica l'utilizzo di getUserById() in quanto è sempre possibile rispondere alla promessa e non è necessario utilizzare il proprio gestore di eccezioni attorno ad esso.

Senza Promise.try(), è possibile codificare la stessa cosa da soli come questo (per catturare tutte le eccezioni possibili sincrone all'interno della funzione):

function getUserById(id) { 
    try { 
     if (typeof id !== "number") { 
      throw new Error("id must be a number"); 
     } 
     return db.getUserById(id); 
    } catch(e) { 
     return Promise.reject(e); 
    } 
} 

getUserById().then(successFn, errFn); 

Oppure, si potrebbe codice in questo modo:

function getUserById(id) { 
    if (typeof id !== "number") { 
     throw new Error("id must be a number"); 
    } 
    return db.getUserById(id); 
} 

try { 
    getUserById().then(successFn, errFn); 
} catch(e) { 
    errFn(e); 
} 

Presumibilmente, è possibile vedere come Promise.try() può semplificare le cose in alcune circostanze.


FYI, nel tuo primo esempio, stai usando una sintassi non valida.È possibile farlo:

reject(throw new Error('error')); 

Sto assumendo quello che volevi dire era questo:

reject(new Error('error')); 

Anche se non credo che questo è davvero quello che stavi chiedendo circa, sarà anche Promise.try() restituire automaticamente una promessa risolta se non si restituisce una promessa da soli. Poiché un percorso del primo esempio non viene risolto o rifiutato, ciò causerà una differenza nei due esempi.

3

Non sono la stessa cosa.

Considerare la situazione in cui entrambe le affermazioni sono false. In tal caso, multiRejectExample() non rifiuterà mai o risolvere la promessa restituita, mentre tryExample() "fallirà" e risolverà automaticamente la promessa (con un valore di undefined perché non si restituisce nulla).

Per dimostrare:

var Promise = require('bluebird'); 

function test1() { 
    return Promise.try(function() { }); 
} 

function test2() { 
    return new Promise(function(resolve, reject) { }); 
} 

test1().then(function() { console.log('resolved #1'); }); 
test2().then(function() { console.log('resolved #2'); }); 

Questo registrerà resolved #1 ma non resolved #2 perché la promessa è mai realmente risolto (né rifiutata).

3

Le seguenti sono le stesse?

No. Come già citato da @robertklep, hanno risultati diversi quando statement è falso. Promise.try rileva le eccezioni e in caso contrario risolve il valore restituito dalla funzione, mentre il costruttore Promise crea appena una nuova promessa e non gli interessa quando non è mai resolve() d.

Quando dovrei usare quale?

Si dovrebbe usare l'IFF Promise costruttore e davvero solo se, siete promisifying an asynchronous callback API. Tutto il resto, in particolare lo when involving other promises, è fondamentalmente un antipattern.
Quindi non usare come nella domanda.

In genere non lo è neanche throw. Stai scrivendo una funzione che restituisce una promessa (perché è asincrona) e dovrebbe sempre restituire una promessa. Se si desidera restituire una promessa respinta con un errore, è possibile crearne una esplicitamente utilizzando Promise.reject. L'approccio corretto sarebbe quindi

function multiRejectExample(){ 
    if (statement){ 
     console.log('statement 1'); 
     return Promise.reject(new Error('error')); 
    } 
    if (statement){ 
     console.log('statement 2'); 
     return Promise.reject(new Error('error')); 
    } 
    return Promise.resolve(); 
} 

Naturalmente, questo particolare esempio non ha molto senso, perché nessuno dei vostri casi è asincrona e non c'è alcun motivo per utilizzare le promesse a tutti. Basta usare una funzione sincrona che genera eccezioni. Tipicamente, avresti qualche return … alla fine che è una promessa effettivamente asincrona, non una che è soddisfatta con undefined.

Ora, se si dispone di una tale funzione, e sono stanchi di scrivere più volte return Promise.reject, è possibile utilizzare i Bluebird-specifici Promise.try e Promise.method metodi come zucchero sintattico.

Problemi correlati