sincronas - ¿Cómo abortar correctamente una cadena de promesa node.js usando Q?
promise javascript (3)
Estoy utilizando el módulo Q para Node.js en un intento de evitar la "pirámide de la fatalidad" en escenarios en los que tengo muchos pasos. Por ejemplo:
function doTask(task, callback)
{
Q.ncall(task.step1, task)
.then(function(result1){
return Q.ncall(task.step2, task);
})
.then(function(result2){
return Q.ncall(task.step3, task);
})
.fail(callback).end();
}
Esencialmente, esto parece funcionar; si se produce un error en alguno de los pasos de la tarea, se pasa a la devolución de llamada (aunque sería bienvenido a las mejoras, ya que soy nuevo en las promesas de node.js). Sin embargo, tengo un problema cuando necesito abortar la cadena de tareas temprano. Por ejemplo, si result1 se devuelve con éxito, es posible que desee llamar a la devolución de llamada anticipadamente y abortar el resto, pero mis intentos de hacerlo están fallando ...
function doTask(task, callback)
{
Q.ncall(task.step1, task)
.then(function(result1){
if(result1)
{// the rest of the task chain is unnecessary
console.log(''aborting!'');
callback(null, result1);
return null;
}
return Q.ncall(task.step2, task);
})
.then(function(result2){
console.log(''doing step 3...'');
return Q.ncall(task.step3, task);
})
.fail(callback).end();
}
En este ejemplo, veo ambos "abortar". y "haciendo el paso 3 ..." impreso.
Estoy seguro de que estoy simplemente malinterpretando algunos principios básicos aquí, por lo que agradecería cualquier ayuda. ¡Gracias!
Creo que solo tienes que rechazar la promesa de salir de la cadena de la promesa.
https://github.com/kriskowal/q/wiki/API-Reference#qrejectreason
también parece que .end () ha sido cambiado a .done ()
function doTask(task, callback)
{
Q.ncall(task.step1, task)
.then(function(result1){
if(result1)
{// the rest of the task chain is unnecessary
console.log(''aborting!'');
// by calling Q.reject, your second .then is skipped,
// only the .fail is executed.
// result1 will be passed to your callback in the .fail call
return Q.reject(result1);
}
return Q.ncall(task.step2, task);
})
.then(function(result2){
console.log(''doing step 3...'');
return Q.ncall(task.step3, task);
})
.fail(callback).done();
}
Cualquier error que se genere dentro de la cadena de la promesa provocará que toda la pila se cancele anticipadamente y se otorgue control a la ruta de error. (en este caso, el controlador fail ()) Cuando detecta un determinado estado que hace que desee abortar la cadena de la promesa, entonces simplemente arroje un error muy específico, que atrapa en el error e ignora (si lo hace escoger)
function doTask(task, callback)
{
Q.ncall(task.step1, task)
.then(function(result1){
if(result1 == ''some failure state I want to cause abortion'')
{// the rest of the task chain is unnecessary
console.log(''aborting!'');
throw new Error(''abort promise chain'');
return null;
}
return Q.ncall(task.step2, task);
})
.then(function(result2){
console.log(''doing step 3...'');
return Q.ncall(task.step3, task);
})
.fail(function(err) {
if (err.message === ''abort promise chain'') {
// just swallow error because chain was intentionally aborted
}
else {
// else let the error bubble up because it''s coming from somewhere else
throw err;
}
})
.end();
}
Este es un caso en el que tendrá que bifurcarse, lo que significa anidar o crear una subrutina.
function doTask(task, callback) {
return Q.ncall(task.step1, task)
.then(function(result1) {
if (result1) return result1;
return Q.ncall(task.step2, task)
.then(function(result2) {
return Q.ncall(task.step3, task);
})
})
.nodeify(callback)
}
O
function doTask(task, callback) {
return Q.ncall(task.step1, task)
.then(function(result1) {
if (result1) {
return result1;
} else {
return continueTasks(task);
}
})
.nodeify(callback)
}
function continueTasks(task) {
return Q.ncall(task.step2, task)
.then(function(result2) {
return Q.ncall(task.step3, task);
})
}