2013-10-30 5 views
6

Re: https://github.com/tildeio/rsvp.jsWie rsvp.js Griffe Versprechen mit Kette des Scheiterns Rückrufe abgelehnt

Ich habe eine Funktion namens doSomething(), die etwas für eine kleine Weile tut und gibt dann eine RSVP.Promise. Dann wird eine Kette von Erfolgs- und Fehlerrückrufen mit dem zurückgegebenen Versprechen registriert (siehe Code unten). Das Verhalten, das ich erwartete war, wenn das Versprechen erfüllt ist, wird die Kette der Erfolg Callbacks mit das Versprechen gefeuert werden, und wenn das Versprechen abgelehnt wird (fehlschlägt), die Kette von Fehlerrückrufe ausgelöst werden.

Ich bekomme das erwartete Verhalten für, wenn das Versprechen erfüllt ist, aber ich bekomme ein Verhalten anders als erwartet, wenn das Versprechen abgelehnt wird. Das heißt, Die Erfolgsrückrufe werden verkettet und die Ausgabe eines Erfolgsrückrufs wird an den nächsten Erfolgsrückruf in der Kette an weitergeleitet. Aber es scheint, die Fehler Callbacks sind nicht verkettet. Sie verhalten sich fast wie der Catch in einem try/catch-Block (siehe Code und Ausgabe unten).

Kann jemand dieses Verhalten erklären? Ist das wirklich die Art, wie es funktionieren soll, oder ist dies ein Fehler in der Art und Weise, wie rsvp.js eine abgelehnte/fehlgeschlagene Zusage verarbeitet, bei der eine Kette von Fehlerrückrufen registriert ist? Ich lese jetzt die Promises/A + -Spezifikation, um zu versuchen, das herauszufinden, aber wenn jemand dieses Zeug von ganz oben kennt, würde ich gerne deine Erklärung hören. Danke im Voraus.

jsfiddle: http://jsfiddle.net/rylie/VYSj7/2/

doSomething() // returns an RSVP.Promise object 
    .then(
     function(message) { console.log("then success 1: " + message); return "from success 1"; }, // success callback 
     function(message) { console.log("then failure 1: " + message); return "from failure 1"; } // failure callback 
    ) 
    .then(
     function(message) { console.log("then success 2: " + message); return "from success 2"; }, // success callback 
     function(message) { console.log("then failure 2: " + message); return "from failure 2"; } // failure callback 
    ) 
    .then(
     function(message) { console.log("then success 3: " + message); return "from success 3"; } // success callback 
    ) 
    .then(
     null, 
     function(message) { console.log("then failure 4: " + message); return "from failure 4"; } // failure callback 
    ) 
    .then(
     function(message) { console.log("then success 5: " + message); return "from success 5"; }, // success callback 
     function(message) { console.log("then failure 5: " + message); return "from failure 5"; } // failure callback 
    ); 

** Wenn das Versprechen (erfolgreich) erfüllt ist, ist dies der Ausgang I erhalten und erwartet:

then success 1: Promise fulfilled! 
then success 2: from success 1 
then success 3: from success 2 
then success 5: from success 3 

** Wenn das Versprechen abgelehnt wird (nicht), das ist die Ausgabe, die ich bekomme:

then failure 1: Promise rejected! 
then success 2: from failure 1 
then success 3: from success 2 
then success 5: from success 3 

** Dies ist, was ich erwartet habe (auf einem abgelehnten/Gescheiterte Versprechen):

then failure 1: Promise rejected! 
then failure 2: from failure 1 
then failure 4: from failure 2 
then failure 5: from failure 4  

Antwort

11

Sie sollten nur vergessen, dass .then() sogar mehr als 1 Argument und verwenden Sie die .catch Methode nimmt und es wird mehr Sinn machen.

Versprechen bieten eine Entsprechung zu einigen Sync-Code-Konstrukten, aber dies ist nicht sehr sichtbar, wenn Sie nur eine Low-Level haben. Was Sie suchen, ist im Grunde eine Reihe von Callbacks/Callback-Aggregation, aber das ist nicht der Punkt der Versprechen überhaupt.

Denken Sie an .catch(fn) gleichen wie .then(null, fn):

doSomething().then(function(val) { 
    console.log(val); 
}).catch(function(e) { 
    console.error(e); 
}); 

Parallels die Sync-Code (man stelle sich doSomething kehrt synchron):

try { 
    var val = doSomething(); 
    console.log(val); 
} 
catch(e) { 
    console.error(e); 
} 

Mehrere Fangmengen (nicht vergessen, dass .catch ist besser lesbar Alias ​​.then(null, fn)

doSomething().then(function(val) { 
    console.log(val); 
}).catch(function(e) { 
    return e; 
}).catch(function(e){ 
    //Will not get here ever 
    //because error thrown from doSomething() 
    //was handled in the upper catch which doesn't trow 
}); 

Parallels:

try { 
    try { 
     var val = doSomething(); 
     console.log(val); 
    } 
    catch(e) { 
     //no need for explicit return e 
    } 
} 
catch(e) { 
    //Will not get here ever 
    //because error thrown from doSomething() 
    //was handled in the upper catch which doesn't trow 
} 

Sie sollten also jetzt feststellen, dass Sie das erwartete Ergebnis durch das Werfen statt Rückkehr http://jsfiddle.net/VYSj7/3/ schaffen

.catch() ist IMO ein wichtiges Verfahren für ein Versprechen Bibliothek zur Verfügung zu stellen und auch sein in den eingebauten Javascript-Versprechen in Zukunft enthalten. Allerdings , wenn ein solches Verfahren nicht vorgesehen ist, können Sie (oder sein sollte, leider gibt es Implementierungen, die Prototypen nicht verwenden):

Promise.prototype.catch = function(fn) { 
    return this.then(null, fn); 
}; 

Siehe auch rejection turns into fulfillment

+0

Nizza Erklärung, Esailija! Vielen Dank. – RBR