2015-08-21 13 views
5

Wann sollte ich welche verwenden? Sind die folgenden gleich?Bluebird.JS Versprechen: neues Versprechen (Funktion (auflösen, ablehnen) {}) vs Promise.try (Funktion() {})

neues Promise() Beispiel:

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() Beispiel:

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

lose verwandt: [Promise.reject vs Wurf Fehler] (http://stackoverflow.com/q/28703241/1048572). Sie sollten den Konstruktor "new Promise" nicht verwenden, wenn Sie nicht gerade etwas Asynchrones tun. Der richtige Ansatz wäre, 'Promise.reject (...)' zurückzugeben (oder 'Promise.try' /' Promise.method' zu verwenden). – Bergi

Antwort

8

können Sie meist entweder in diesem Fall (mit einem Verhalten Unterschied). Die erste ist die Standardversprechensfunktionalität und funktioniert mit jeder beliebigen Versprechungsbibliothek.

Promise.try() ist ein Feature, das speziell von der Bluebird-Bibliothek implementiert wurde und ist nicht Teil eines mir bekannten Standardprozesses.

Der Grund für die Verwendung von Promise.try() ist, wenn Sie eine Funktion haben, die ein Versprechen zurückgibt, aber der Code, der dieses Versprechen generiert, kann auch eine synchrone Ausnahme verursachen. Da diese Ausnahme nicht in einem Verspreenter-Handler enthalten ist, haben Sie eine Mischung aus Fehlerbehandlung. Einige Codeausführungspfade können dazu führen, dass ein Versprechen zurückgegeben wird, das auflösen oder zurückweisen würde, und andere Codeausführungspfade könnten eine Ausnahme auslösen. Um dies sicher zu verschlüsseln, müssten Sie beide auf das Versprechen reagieren und einen try/catch-Block um den Code setzen, der unhandlich wird.

Promise.try() ist einfach ein Mittel zum automatischen Abfangen von Ausnahmen und deren Umwandlung in eine Zurückweisung (ähnlich wie in Handlern).

In Ihren beiden Fällen profitieren Sie Promise.try() nicht auf diese Weise, weil der Rückruf new Promise() bereits Ausnahmen abfängt und sie in Ablehnungen umwandelt, so dass die Funktionalität dort für Sie bereits ausgeführt wird. Sie können das hier demonstriert sehen: http://jsfiddle.net/jfriend00/wLov9844/

Die Drossel-doc dieses Beispiel bietet das den Vorteil deutlicher zeigt:

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

Die Verwendung von Promise.try() hier stellt sicher, dass getUserById() ein Versprechen immer wieder zurückkehren, auch wenn der Code innerhalb dieser Methode löst eine Ausnahme synchron aus. Dies vereinfacht die Verwendung von getUserById(), da Sie immer nur auf das Versprechen reagieren können und nicht Ihren eigenen Ausnahme-Handler darum verwenden müssen.

Ohne Promise.try(), könnten Sie die gleiche Sache selbst wie dieser Code (alle möglichen synchronen Ausnahmen innerhalb der Funktion zu fangen):

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

Oder Sie es wie folgt Code könnte:

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

Vermutlich können Sie sehen, wie Promise.try() unter bestimmten Umständen die Dinge vereinfachen kann.


FYI, in Ihrem ersten Beispiel verwenden Sie ungültige Syntax.Sie können dies tun:

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

Ich gehe davon aus, was du damit gemeint war:

reject(new Error('error')); 

Obwohl ich nicht glaube, das ist wirklich, was Sie fragten, Promise.try() wird auch geben automatisch ein aufgelöstes Versprechen zurück, wenn Sie kein Versprechen selbst zurückgeben. Da ein Pfad in Ihrem ersten Beispiel nicht aufgelöst oder abgelehnt wird, führt dies zu einem Unterschied in Ihren beiden Beispielen.

3

Sie sind nicht das Gleiche.

Betrachten Sie die Situation, in der beide Aussagen falsch sind. In diesem Fall wird multiRejectExample() niemals oder das zurückgegebene Versprechen lösen, während tryExample() "durchfallen" und das Versprechen automatisch lösen (mit einem Wert von undefined, weil Sie nichts zurückgeben).

Um zu demonstrieren:

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

Diese resolved #1 log, aber nicht resolved #2 weil das Versprechen tatsächlich behoben ist nie (noch abgelehnt).

3

Sind die folgenden gleich?

Nein. Wie @robertklep bereits erwähnt, haben sie unterschiedliche Ergebnisse, wenn statement falsch ist. Promise.try fängt Ausnahmen ab und löst andernfalls mit dem Rückgabewert der Funktion auf, während der Promise Konstruktor nur ein neues Versprechen erstellt und es nicht interessiert, wenn es nie resolve() d.

Wann sollte ich welches verwenden?

Sie sollten den Promise Konstruktor iff verwenden und wirklich nur, wenn, sind Sie promisifying an asynchronous callback API. Alles andere, besonders when involving other promises, ist im Grunde ein Antipattern.
So verwenden Sie es nicht wie Sie in Ihrer Frage haben.

Sie normalerweise nicht throw entweder. Sie schreiben eine Funktion, die eine Zusage zurückgibt (weil sie asynchron ist), und sie sollte immer eine Zusage zurückgeben. Wenn Sie eine Zusage zurückgeben möchten, die mit einem Fehler abgelehnt wurde, können Sie diese explizit erstellen, indem Sie Promise.reject verwenden. Der richtige Ansatz wäre daher

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

Natürlich dieses Beispiel macht nicht viel Sinn machen, weil keiner Ihrer Fälle asynchron ist, und es gibt keinen Grund, Versprechen zu verwenden überhaupt. Verwenden Sie einfach eine synchrone Funktion, die Ausnahmen auslöst. In der Regel haben Sie am Ende einige return …, die eine tatsächliche asynchrone Versprechen ist, nicht eine, die mit undefined erfüllt ist.

Nun, wenn Sie eine solche Funktion haben, und sind müde von return Promise.reject wiederholt zu schreiben, können Sie die Drossel spezifische Promise.try und Promise.method Methoden wie syntaktischer Zucker verwenden.

Verwandte Themen