Async: rompiendo la cadena de la cascada sin arrojar un error

Creado en 15 feb. 2011  ·  8Comentarios  ·  Fuente: caolan/async

Me dijeron que necesito refactorizar mi código que usa cascada asíncrona. Lo usé principalmente porque tenía varias funciones encadenadas que iban demasiado profundas y quería reutilizar una función, etc. Hay una condición en un punto de la cadena que no es estrictamente una condición de error, pero que no quiero pasar el resto de la cadena de la cascada, porque es inútil, digamos que, por ejemplo, hice una consulta y no hay resultados, y eso no es un error, no quiero propagar todo el camino hacia abajo sin resultados. Si estuviera haciendo esto sin async, supongo que tendría una devolución de llamada "final" y que podría llamarse para salir de la cadena sin arrojar explícitamente un error. Esta funcionalidad no parece estar presente en cascada. ¿Hay alguna manera de hacer esto limpiamente? La única forma que puedo ver para hacerlo es lanzar un error especial y luego manejarlo en la devolución de llamada final para devolver un no error.

Comentario más útil

Personalmente, me encuentro necesitando una funcionalidad como esta y creo que debería agregarse a la biblioteca central.

Aquí está mi solución alternativa si alguien está interesado ...

exports.breakWaterfall = function(tasks, callback){
    async.waterfall(tasks, function(){
        if(arguments[0] === 'break'){
            arguments[0] = null;
        }
        callback.apply(null, arguments);
    });
}

Si necesita ir a la última función dentro de una tarea, simplemente llame a la devolución de llamada así: done('break', other, arguments); .

El ayudante simplemente detecta el 'break' y muta los argumentos para que no parezca un error en el resto de su código.

Todos 8 comentarios

Hola,

Probablemente ya hayas resuelto tu problema, por cierto, este es mi enfoque:

var flow = [
    async.apply(...),
    // ...
];

async.waterfall(flow, function (err) {
    if (err === 'ok') return;
    // handle error
});

Cuando una función llama a una devolución de llamada con err = 'ok' , la devolución de llamada final de la cascada la intercepta.

Tengo un problema similar y estoy agregando un contenedor de devolución de llamada (que podría evitar) solo para verificar si es un error o no para cada cascada que uso. No es tan limpio cuando hay más de una cascada.
¿Puede la función de devolución de llamada en sí misma tener otra propiedad llamada 'final', a la que la gente podría llamar para ir al final?
Algo como

function search (cond, callback) {
  async.waterfall([function (cb) {
      db.get(cond, cb);
    },
    function (res, cb) {
      if (!res || !res.length)
        return cb.final();
      //do something useful
    }
  ], callback);
}

No tendré que envolver la devolución de llamada y podría encadenarse al resto del programa.

@caolan, ¿hay algo que no te guste de la solicitud de extracción de

@tax : de hecho, descubrí que podemos saltar a la función final pasando 'error' = true así:

async.waterfall ([función (devolución de llamada) {
devolución de llamada (nulo); // <--- ir a la siguiente fn
},
function (devolución de llamada) {
devolución de llamada (verdadero); // <--- saltar al último fn
},
function (devolución de llamada) {
devolución de llamada (nulo); // <--- esta fn no será llamada
}
], llamar de vuelta);

@ tot2ivn gracias por la sugerencia!

Sin embargo, si establece el error, el resultado estará vacío.

var async = require('async');

async.waterfall( [
  function( callback ){
    console.log('one');
    callback( null );
  },

  function( callback ){
    console.log('two');
    callback( true, 'more info' );
  },

  function( callback ){
    console.log('three');
    callback( null );
  }
], function(err, result){
  console.log( err, result );
} );

// RESULT
// one
// two
// true undefined

A la luz del comentario de

Personalmente, me encuentro necesitando una funcionalidad como esta y creo que debería agregarse a la biblioteca central.

Aquí está mi solución alternativa si alguien está interesado ...

exports.breakWaterfall = function(tasks, callback){
    async.waterfall(tasks, function(){
        if(arguments[0] === 'break'){
            arguments[0] = null;
        }
        callback.apply(null, arguments);
    });
}

Si necesita ir a la última función dentro de una tarea, simplemente llame a la devolución de llamada así: done('break', other, arguments); .

El ayudante simplemente detecta el 'break' y muta los argumentos para que no parezca un error en el resto de su código.

¿Fue útil esta página
0 / 5 - 0 calificaciones