Async: briser la chaîne en cascade sans lancer d'erreur

Créé le 15 févr. 2011  ·  8Commentaires  ·  Source: caolan/async

On m'a dit que je devais refactoriser mon code qui utilise une cascade asynchrone. Je l'ai utilisé principalement parce que j'avais plusieurs fonctions enchaînées qui allaient trop loin et que je voulais réutiliser une fonction, etc. Il y a une condition à un moment donné dans la chaîne qui n'est pas strictement une condition d'erreur, mais que je ne fais pas Je veux transmettre le reste de la chaîne en cascade, car c'est inutile - disons, par exemple, que j'ai fait une requête et qu'il n'y a aucun résultat, et ce n'est pas une erreur, je ne veux pas me propager jusqu'en bas sans résultat. Si je faisais cela sans async, je suppose que j'aurais un rappel "final" et qui pourrait être appelé pour sortir de la chaîne sans lancer explicitement une erreur. Cette fonctionnalité ne semble pas être présente dans la cascade. Y a-t-il un moyen de le faire proprement? La seule façon que je vois de le faire est de lancer une erreur spéciale, puis de la gérer lors du rappel final afin de renvoyer une erreur non.

Commentaire le plus utile

Personnellement, j'ai besoin de fonctionnalités comme celle-ci et je pense qu'elles devraient être ajoutées à la bibliothèque principale.

Voici ma solution de contournement d'aide si quelqu'un est intéressé...

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

Si vous devez passer à la dernière fonction d'une tâche, appelez simplement le rappel comme ceci : done('break', other, arguments); .

L'assistant détecte simplement le 'break' et mute les arguments afin que cela ne ressemble pas à une erreur pour le reste de votre code.

Tous les 8 commentaires

Salut,

vous avez probablement déjà résolu votre problème, voici mon approche :

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

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

Lorsqu'une fonction appelle un rappel avec err = 'ok' , le rappel final de la cascade l'intercepte.

J'ai un problème similaire et j'ajoute un wrapper de rappel (que je pourrais éviter) juste pour vérifier s'il s'agit d'une erreur ou non pour chaque cascade que j'utilise. Ce n'est pas si propre quand il y a plus d'une cascade.
La fonction de rappel elle-même peut-elle avoir une autre propriété appelée 'final', que les gens pourraient appeler pour aller à la fin.
Quelque chose comme

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

je n'aurai pas à envelopper le rappel et il pourrait être enchaîné au reste du programme.

@caolan y a-t-il quelque chose que vous n'aimez pas dans la pull request

@tax : en fait, j'ai trouvé que nous pouvons passer à la fonction finale en passant 'error' = true comme ceci :

async.waterfall([fonction (rappel) {
rappel (null); // <--- aller à la fn suivante
},
fonction (rappel) {
rappel (vrai); // <--- passer à la dernière fn
},
fonction (rappel) {
rappel (null); // <--- cette fn ne sera pas appelée
}
], rappeler);

@tot2ivn merci pour le conseil !

Si vous définissez l'erreur, le résultat sera cependant vide.

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

À la lumière du commentaire de

Personnellement, j'ai besoin de fonctionnalités comme celle-ci et je pense qu'elles devraient être ajoutées à la bibliothèque principale.

Voici ma solution de contournement d'aide si quelqu'un est intéressé...

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

Si vous devez passer à la dernière fonction d'une tâche, appelez simplement le rappel comme ceci : done('break', other, arguments); .

L'assistant détecte simplement le 'break' et mute les arguments afin que cela ne ressemble pas à une erreur pour le reste de votre code.

Cette page vous a été utile?
0 / 5 - 0 notes