dejavu
dejavu

Reputation: 3254

Async.js design pattern

I am using async.js for my node.js app. I need help solving the following problem.

Let's say I have a following aysnc js series function.

async.waterfall([
    function getDataFromDB(request, response, callback){ ... },
    function someOperationOnDBData(dbData, response, callback){ ... },
    function renderSomeFlow(evaluatedData, response, callback){ ... }
]);

I have three functions called in the order mentioned above. I am getting data from getDataFromDB and passing to someOperationOnDBData and so on.

Suppose I need one more operation in between getDataFromDB and someOperationOnDBData but still pass DBData forward. Eg:

async.waterfall([
    function getDataFromDB(request, response, callback){ ... },
    function extraOperation(dbData, response, callback) {...}
    function someOperationOnDBData(dbData, extraOperationData, response, callback){ ... },
    function renderSomeFlow(evaluatedData, response, callback){ ... }
]);

Here adding a single step in the middle changes the function definitions and also I need to pass dbData in extraOperation to just forward it to someOperationOnDBData. Also, if I am calling a different module in the middle, it might not be possible to change it's parameter to forward some data.

How to solve this problem of passing data between functions in async.js without forwarding data in middle functions? Refactoring functions every time a new step is included is not possible. What is the design pattern for solving this type of problem?

Upvotes: 4

Views: 280

Answers (2)

YeeHaw1234
YeeHaw1234

Reputation: 2495

I've found that currying your functions with arrow functions is a way arround this problem:

const someOperationOnDBData = extraOperationData => (dbData, response, callback) => {
  // do your function work
};

async.waterfall([
  function getDataFromDB(request, response, callback){ ... },
  function extraOperation(dbData, response, callback) {...}
  someOperationOnDBData(extraOperationData)(dbData, response, callback),
  function renderSomeFlow(evaluatedData, response, callback){ ... }
]);

Many good examples on how to curry javascript functions on Medium.com

Upvotes: 0

MrWillihog
MrWillihog

Reputation: 2646

Using waterfall you have to pass the data through - you can't stop a waterfall in the middle :). There are alternatives that you might like to use, for example, auto which lets you specify which functions depend on the results of other functions and async will determine the best order to run them.

I find the syntax of auto a little awkward but it does what you need. Here is an example:

async.auto({
    db: function getDataFromDB(callback){ ... },
    extra: ['db', function extraOperation(results, callback) {...}],
    some: ['db', function someOperationOnDBData(results, callback){ ... }],
    render: ['some', 'db', function renderSomeFlow(results, callback){ ... }]
});

Upvotes: 4

Related Questions