Asyncjs : Bypass a function in a waterfall chain

2019-04-07 22:07发布

I want to jump a function from a chain of waterfall functions with asyncjs in nodejs.

My code look like this :

async.waterfall([
    function(next){
        if(myBool){
            next(null);
        }else{
            // Bypass the 2nd function
        }
    },

    // I want to bypass this method if myBool is false in the 1st function
    function(next){
    },

    // Always called
    function(next){
    }
]);

Do you know a proper way to do this without put :

if(!myBool){
    return next();
}

In the function I want to bypass.

Thanks !

5条回答
混吃等死
2楼-- · 2019-04-07 22:38

I think this should work:

var finalCallback = function(err, result){
  if(err)
     // handle error..
  else
     console.log('end! :D');
}

async.waterfall(
  [
    function step1(callback){
       // stuff
       callback(null, someData);
    },
    function step2(someData, callback){
       if(skip_step_3)
          finalCallback(null, someData);
       else
          callback(null, someData);
    },
    function step3(moreData, callback){
       // more stuff
       callback(null, moreData);
    }
  ],
  finalCallback
)

the creator of async recomend this in the github repo (https://github.com/caolan/async/pull/85)

查看更多
放荡不羁爱自由
3楼-- · 2019-04-07 22:42

I would recommend using clojurescript which has an awesome core-async library which makes life super easy when dealing with async calls.

In your case, you would write something like this:

(go
  (when-let [res1 (<! (asyncFunc1))]
    (<! (asyncFunc2 res1)))
  (<! (asyncFunc3)))

Note the go macro which will cause the body to run asynchronously, and the <! function which will block until the async functions will return.

The code will first block on the first async function. Then, if the result of that is true, it will run the second async function on block on that as well. Lastly, it will run the third async function and block on that.

查看更多
倾城 Initia
4楼-- · 2019-04-07 22:50

An alternative might be:

var tasks = [f1];

if(myBool){
    tasks.push(f2);
}

tasks.push(f3);

async.waterfall(tasks, function(err, result){
});

where f1, f2, and f3 are your functions.

other than that, you're better off doing it explicitly, avoid making your code overly complicated, simpler is usually better

update:

function f1(done){
    if(myBool){
        f2(done);
    }else{
        done();
    }
}

function f2(done){
    async.nextTick(function(){
        // stuff
        done();
    });
}

async.waterfall([f1,f3],function(err,result){
    // foo
});
查看更多
唯我独甜
5楼-- · 2019-04-07 22:57

Using if-async module your code will look like this:

var async = require('async')
var ifAsync = require('if-async')

async.waterfall([
    foo,
    ifAsync(p1).then(c1).else(c2),
    bar
], function(err) {})

for full example take a look here: https://github.com/kessler/if-async#example-2-using-with-asyncjs-waterfall

查看更多
祖国的老花朵
6楼-- · 2019-04-07 23:04

I am late to answer, but async-if-else might help you.

Sample Code

 var async = require('async-if-else')(require('async'));

  function emailExists(user, callback) {
    user.find(user.email, function(err, dbUser){
      if (err)
        return callback(error);

      if(!dbUser)
     return callback(null, false); // does not exist, predicate will be false 

   callback(null, true);  
  });
  }

  function updateAccount(user, callback) { 
    user.update( ..., callback);
  }

  function importFromLegacyByEmail(user, callback) { 
    remoteClient.get(user, callback);
  }

  async.waterfall([
    async.constant({email: 'thiago@email.com', dogs: 2, money: 0, fun: 100 }),
    async.if(emailExists, updateAccount).else(importFromLegacyByEmail),
    sendEmail
  ], handler);
查看更多
登录 后发表回答