2013-10-30 23 views
6

Re: https://github.com/tildeio/rsvp.jsCome rsvp.js maniglie respinti promessa con catena di callback guasto

ho una funzione chiamata doSomething(), che fa qualcosa per un po 'e poi restituisce un RSVP.Promise. Quindi, una catena di callback riusciti e non riusciti è registrata con la promessa restituita (vedere il codice seguente). Il comportamento che mi aspettavo è stato, se la promessa è soddisfatta, la catena di callback di successo registrati con la promessa verrà licenziata, e se la promessa viene respinta (non riesce), la catena di callback di errori fallirà.

Ho il comportamento previsto per quando la promessa è soddisfatta, ma ottengo un comportamento diverso da quello che mi aspettavo quando la promessa è stata respinta. Cioè, i callback di successo sono concatenati e l'output di una callback riuscita viene passato a il prossimo callback di successo nella catena. Ma sembra che le callback di errore non siano concatenate. Si comportano quasi come il fermo in un blocco try/catch (vedi codice e output di seguito).

Qualcuno può spiegare questo comportamento? È davvero così che si suppone che funzioni, oppure è questo un errore nel modo in cui rsvp.js gestisce una promessa rifiutata/fallita che ha una catena di callback di errore registrati con esso? Sto leggendo ora le specifiche Promises/A + per cercare di capirlo, ma se qualcuno conosce questa roba dalla testa, mi piacerebbe sentire la tua spiegazione. Grazie in anticipo.

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

** Quando la promessa si compie (riesce), questo è l'uscita ottengo e prevede:

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

** Quando la promessa viene rifiutata (fallisce), questo è il risultato che ottengo:

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

** questo è quello che mi aspettavo (su una respinta/Promessa fallito):

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

risposta

11

si dovrebbe solo dimenticare che .then() richiede anche più di 1 argomento e utilizzare il metodo .catch e renderà più senso.

Promesse forniscono una corrispondenza con alcuni costrutti di codice di sincronizzazione, ma questo non è molto visibile quando hai solo un basso livello di .then(). Quello che stai cercando è fondamentalmente una serie di callback/aggregazione di callback, ma questo non è affatto il punto delle promesse.

Pensate .catch(fn) stesso .then(null, fn):

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

Parallels il codice di sincronizzazione (immaginate doSomething restituisce sincrono):

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

catture multiple (ricordiamo che .catch è alias più leggibile per .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 
} 

Così ora si dovrebbe notare che è possibile creare il risultato previsto gettando invece di tornare http://jsfiddle.net/VYSj7/3/

.catch() è IMO un metodo essenziale per una libreria promessa di fornire e saranno anche incluso nelle promesse di Javascript incorporate in futuro. Tuttavia, se tale metodo non viene fornito, si può (o dovrebbe essere, purtroppo ci sono implementazioni che non utilizzano i prototipi):

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

Vedi anche rejection turns into fulfillment

+0

bella spiegazione, Esailija! Grazie. – RBR

Problemi correlati