Disseram-me que preciso refatorar meu código que está usando a cascata assíncrona. Usei-o principalmente porque tinha várias funções encadeadas que estavam indo muito fundo e queria reutilizar uma função, etc. Há uma condição em um ponto abaixo da cadeia que não é estritamente uma condição de erro, mas eu não quero passar o resto da cadeia em cascata, porque é inútil - digamos, por exemplo, fiz uma consulta e não há resultados, e isso não é um erro, não quero propagar todo o caminho sem resultados. Se eu estivesse fazendo isso sem assíncrono, acho que teria um retorno de chamada "final" e que poderia ser chamado para quebrar a cadeia sem gerar um erro explicitamente. Esta funcionalidade não parece estar presente em cascata. Existe uma maneira de fazer isso de forma limpa? A única maneira que vejo de fazer isso é lançar um erro especial e, em seguida, lidar com isso no retorno de chamada final para retornar um erro não.
Oi,
você provavelmente já resolveu seu problema, a propósito, esta é a minha abordagem:
var flow = [
async.apply(...),
// ...
];
async.waterfall(flow, function (err) {
if (err === 'ok') return;
// handle error
});
Quando uma função chama um retorno de chamada com err = 'ok'
, o retorno de chamada final da cascata o intercepta.
Eu tenho um problema semelhante e estou adicionando um invólucro de retorno de chamada (que eu poderia evitar) apenas para verificar se é um erro ou não para cada cachoeira que uso. Não é tão limpo quando há mais de uma cachoeira.
A própria função de retorno de chamada pode ter outra propriedade chamada 'final', que as pessoas poderiam chamar para ir até o fim?
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);
}
Eu não terei que encerrar o retorno de chamada e pode ser encadeado para o resto do programa.
@caolan, há algo que você não goste na solicitação de pull do @jnordberg ? Em caso afirmativo, há algo que eu possa fazer para que essa solicitação pull seja aceita?
@tax : na verdade, descobri que podemos pular para a função final passando 'error' = true assim:
async.waterfall ([function (callback) {
retorno de chamada (nulo); // <--- ir para o próximo fn
},
function (callback) {
retorno de chamada (verdadeiro); // <--- pular para o último fn
},
function (callback) {
retorno de chamada (nulo); // <--- este fn não será chamado
}
], ligar de volta);
@ tot2ivn obrigado pela dica!
Se você definir o erro, o resultado ficará vazio.
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
À luz do comentário de
Pessoalmente, acho que preciso de uma funcionalidade como essa e acho que ela deveria ser adicionada à biblioteca central.
Aqui está a minha solução alternativa auxiliar, se alguém estiver interessado ...
exports.breakWaterfall = function(tasks, callback){
async.waterfall(tasks, function(){
if(arguments[0] === 'break'){
arguments[0] = null;
}
callback.apply(null, arguments);
});
}
Se você precisar ir para a última função em uma tarefa, basta chamar o callback assim: done('break', other, arguments);
.
O auxiliar apenas detecta 'break'
e altera os argumentos para que o resto do código não pareça um erro.
Comentários muito úteis
Pessoalmente, acho que preciso de uma funcionalidade como essa e acho que ela deveria ser adicionada à biblioteca central.
Aqui está a minha solução alternativa auxiliar, se alguém estiver interessado ...
Se você precisar ir para a última função em uma tarefa, basta chamar o callback assim:
done('break', other, arguments);
.O auxiliar apenas detecta
'break'
e altera os argumentos para que o resto do código não pareça um erro.