nodeJS design pattern to break out of a async.waterfall or promise.then.then

时间:2015-11-12 11:18:11

标签: javascript node.js design-patterns asynchronous bluebird

I have 4 async functions to execute in my node app in a waterfall style.

async.waterfall will tidy it up, but based on the result of the first function, I either want to error, carry on down the waterfall or break out to the finished function.

There is no way to do this at the moment (other than 'Error' with a success value, which just smells bad).

I was looking at using promises, (Bluebird), but again, I don't see a way to break out, if I DON'T return another promise in the .then, then all the following .thens are executed but with null parameters.

Is there another pattern / utility that can help?

or am I over thinking this and just call the first method normally , and then based on the result run the async.waterfall, or return the result!

Assuming I have 4 functions to call, a,b,c,d.....

async.waterfall([
   function(cb) {
       a("some data", cb)
   },
   function(data, cb) {
        if(data) {
            // HERE we want to skip the remaining waterfall a go to the final func
         } else {
            b("some data", cb);
         }
   },
   c,
   d
],

function(err, data) {
    //do something 
 });

Or if they were promises...

a("some data")
.then(function(data) {
    if(data) { 
        // here I want to stop executing the rest of the promises...
    } else {
       return b("some data")
    }
})
.then(c)
.then(d)
.catch(function(err) {
    //log error
})
.finally(function() {
     // do something
})

I'm thinking I should just do this...

function doit(data, done) {
    a("some data", function(err, data) {
       if(err) { return done(err) };
       if(data) { return done(null, data) };

       //Here we run the waterfall if the above doesn't exist.

       async.waterfall([
           function(cb) {
               b("some data", cb)
           },
           c,
           d
        ],
        function(err, data) {
           done(err, data);
        });
}

1 个答案:

答案 0 :(得分:1)

With promises, you can just attach 'followup promises' to the execution branch that you need:

a("some data")
.then(function(data) {
    if(data) { 
        return "foo";//other promises won't be executed here
    } else {
       return b("some data").then(c).then(d)
    }
})
.catch(function(err) {
    //log error
})
.finally(function() {
     // do something
})