2015-07-12 6 views
6

Per rendere questa domanda utile a quante più persone possibile, escluderò i miei specifici dettagli di implementazione oltre al fatto che sto usando la libreria di promessa Bluebird con Node + Express sotto .Bluebird Promise Chains: 'Catch' con Risultato

Quindi, diciamo che ho la seguente catena (dove P restituisce una promessa, e res è l'oggetto di risposta HTTP espresso):

P().then(function(){ 
    // do nothing if all went well (for now) 
    // we only care if there is an error 
}).catch(function(error){ 
    res.status(500).send("An error occurred"); 
}).then(function(){ 
    return P(); 
}).then(function(pVal1){ 
    return [pVal1, P()]; 
}) // TODO: catch an error from P() here and log pVal1 
.spread(function(pVal1, pVal2){ 
    if(pVal1 === pVal2) { 
     console.log("Success!"); 
    } else { 
     console.log("Failure"); 
    } 
}); 

Dove ho messo il commento TODO sopra è dove vorrei Mi piace prendere un errore che potrebbe verificarsi dalla mia chiamata a P. Se riscontro un errore, desidero registrare pVal1 e quindi inviare un errore 500, come si fa nel primo rilevamento. Tuttavia, non sono sicuro che ciò sia possibile con il modo in cui strutturo la mia catena.

Credo di dover fare un po 'di "ramificazione", ma non credo di capire questo concetto abbastanza bene da fermare la natura asincrona di JavaScript da ottenere il meglio di me! Come tale, ogni aiuto è molto apprezzato.

+0

Se sto facendo questo torto nella sua interezza, però, per favore fatemelo sapere! – nmagerko

+1

@torazaburo no non lo è. –

+0

@BenjaminGruenbaum Perché no? –

risposta

2

Non dimenticare di rilevare errori alla fine della catena. Questo è anche il posto dove inviare la risposta.

Gli errori di cattura nel mezzo di una catena sono per la gestione intermittente degli errori; la catena continua a funzionare, quindi non inviare ancora una risposta.

Qui è qualcosa da provare:

// example middleware 
 
function handle(req, res, next) { 
 
    log("----------------"); 
 
    return async("p1", "foo").then(function (pVal1) { 
 
     return pVal1; 
 
    }).then(function (pVal1) { 
 
     var p2a = async("p2a", "bar"), 
 
      p2b = async("p2a", "bar").catch(function (error) { 
 
       log("Logging: " + error + " (pVal1 " + pVal1 + ")"); 
 
      }); 
 
     return [p2a, p2b]; 
 
    }).spread(function (pVal1, pVal2) { 
 
     if (pVal1 === pVal2) { 
 
      res.send("Success!"); 
 
     } else { 
 
      res.send("Failure"); 
 
     } 
 
    }).catch(function (error) { 
 
     res.status(500).send("An error occurred"); 
 
     log("Logging: " + error); 
 
    }); 
 
} 
 

 
// --------------------------------------------------------------------- 
 
// mockup response object 
 
var res = { 
 
    status: function (code) { 
 
     log("Sending status: " + code); 
 
     return this; 
 
    }, 
 
    send: function() { 
 
     log("Sending response: " + [].join.call(arguments, " ")); 
 
     return this; 
 
    } 
 
}; 
 

 
// mockup promise generator 
 
function async(name, value) { 
 
    return new P(function (resolve, reject) { 
 
     if (confirm("let " + name + " succeed?")) { 
 
      log(name + " succeeds..."); 
 
      resolve(value); 
 
     } else { 
 
      log(name + " fails..."); 
 
      reject(name + " has failed"); 
 
     } 
 
    }); 
 
} 
 

 
function log() { 
 
    var msg = document.createElement("DIV"); 
 
    msg.textContent = [].join.call(arguments, " "); 
 
    document.getElementById("log").appendChild(msg) 
 
    document.body.scrollTop = document.body.scrollHeight; 
 
}
button { 
 
    position: fixed; 
 
    top: 5px; 
 
}
<script src="http://cdnjs.cloudflare.com/ajax/libs/bluebird/2.9.33/bluebird.min.js"></script> 
 

 
<button onclick="handle(null, res, null)">Go</button> 
 

 
<div id="log"></div>

+0

Ah, un "catch" all'interno di un "then" è probabilmente quello che mi mancava. Non ho nemmeno pensato di strutturarlo in quel modo. L'esempio rende anche questa una risposta eccellente! – nmagerko

1

Questo è possibile se si utilizza il esplicito Promise.all invece di restituire un array in .spread.

}).then(function(pVal1){ 
    // this becomes a `Promise.all` - the aggregation is explicit 
    var all = Promise.all([pVal1, P()]); 
    all.catch(function(e){ // "branching", we both return and `catch` the promise 
     console.log("Error, pVal1 is", pVal1); 
    }); 
    return all; // return it 
}).spread(function(pVal1, pVal2){ 
     // .... 
}); 
+0

Questo tipo di codice non darebbe un "rifiuto non gestito"? – Bergi

+0

@Bergi provalo :) –

+0

OK, l'ho fatto, sì registra un rifiuto non gestito (la mia impressione era corretta, anche se ancora non capisco completamente le condizioni per "non gestita"). Ma lo vogliamo? – Bergi