Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version of async.series where each task receives the results of all previous tasks #957

Closed
alexpusch opened this issue Nov 16, 2015 · 5 comments

Comments

@alexpusch
Copy link

I frequently encounter a situation where a async.series task need the results of several previous tasks. async.waterfall is insufficient since it only provides the result of the last previous task. async,auto is too verbose, and provides additional, unneeded dependency declaration.

A new function (or an improvment of async.series) would come in handy. Each task would receive a result object containing the results of all previous tasks

Possible names: accumulate, seriesAccumulate

Example:

async.accumulate({
    one: function(callback){
        setTimeout(function(){
            callback(null, 1);
        }, 200);
    },
    two: function(callback, results){
        // results: {one: 1}
        setTimeout(function(){
            callback(null, 2);
        }, 100);
    },
    three: function(callback, results){
         // results: {one: 1, two: 2}
        setTimeout(function(){
            callback(null, results.one + results.two);
        }, 100);
    }
},
function(err, results) {
    // results is now equal to: {one: 1, two: 2, three: 3}
});
@aearly
Copy link
Collaborator

aearly commented Nov 16, 2015

Have you checked out async.auto? It does something very similar to what you describe.

@alexpusch
Copy link
Author

As I mentioned, in a simple series scenario async.auto is too verbose, The user have to declare that each step is dependent on the previous one, resulting in those ugly arrays and duplicate step names

async.auto({
    one: function(callback){
        setTimeout(function(){
            callback(null, 1);
        }, 200);
    },
    two: ["one", function(callback, results){
        setTimeout(function(){
            callback(null, 2);
        }, 100);
    }],
    three: ["two", function(callback, results){
        setTimeout(function(){
            callback(null, results.one + results.two);
        }, 100);
    }
   ]
},
function(err, results) {
    // results is now equal to: {one: 1, two: 2, three: 3}
});

@aearly
Copy link
Collaborator

aearly commented Nov 25, 2015

We are going to make some enhancements to auto in the next major release -- always have the callback last, and also add autoInject (#608) which infers the dependencies from the parameter names.

I don't like this proposal because it relies on the order of the object keys -- something which is not guaranteed across JS environments (and is only guaranteed in Node for small objects). With arrays it is possible, but it is too similar to async.waterfall. I'm not sure we need something in between auto and waterfall, especially if we're adding autoInject.

@aearly
Copy link
Collaborator

aearly commented Nov 25, 2015

A way to accomplish what you want:

function seriesAccumulate(tasks, done) {
  async.reduce(tasks, [], function (results, task, next) {
    task(results, function (err, result) {
      results.push(result);
      next(err, result);
    });
  }, done);
}

I'd recommend against trying to use an object to iterate in series.

@aearly
Copy link
Collaborator

aearly commented Mar 22, 2016

Closing this. I don't think we need another method between series and waterfall in style.

@aearly aearly closed this as completed Mar 22, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants