1

I have started coding in Node.js last week. I have wrote code to generate JSON querying multiple tables and not sure if this is correct way of coding asynchronously

build_actor(post, function(actor){
  build_post_object(post, function(post_object){
    build_post_attachments(post, function(attachments){
      build_post_comments(post, function(comments){
        var post_obj = {};
        post_obj.actor = actor;
        post_obj.object = post_object;
        post_obj.attachments = attachments;
        post_obj.comments = comments;
        console.log(JSON.stringify(post_obj)); // generates JSON
      });
    });
  });
});

function build_actor(post, callback){
  //query
  callback(actor);
}
function build_post_object(post, callback){
  //query
  callback(post_object);
}
function build_post_attachments(post, callback){
  //query
  callback(attachments);
}
function build_post_comments(post, callback){
  //query
  callback(comments);
}

Kindly let me know if there is a better way for writing multiple queries and building a JSON.

1
  • 1
    Take a look at the async library github.com/caolan/async . You can then call all the functions neatly either in series(if they are dependent of each other) or in parallel and then wait for all to finish. The async.parallel seems to be the weapon of choice for you with a finish method which actually takes the full result and does something with it. Commented Aug 26, 2013 at 6:14

1 Answer 1

1

I see that you already got an answer, but I thought I could see if it is possible to make a really elegant solution using async (should be less code and/or easier to read than the original solution), just as an exercise. And it is:

async.series({
  actor: async.apply(build_actor, post),
  post_object: async.apply(build_post_object, post),
  attachments: async.apply(build_post_attachments, post),
  comments: async.apply(build_post_comments, post)
},
function (err, result) {
  console.log(JSON.stringify(result));
});

The build_*-functions must also callback null (or an error) as the first argument. This is generally a good idea since most of node.js' apis and modules work that way. For example:

function build_actor(post, callback) {
  // Query
  callback(null, actor);
}

Note that I haven't actually tested it, but it should work.

So the magic here is that async.series can compose the result as an object, where the keys for the result are the same as you assign the functions. Thus you don't need do assing values to an object but can convert it straight away. async.apply is just a more simple way of calling a function with an already available argument. The plain way would be:

function (callback) {
  build_actor(post, callback);
}

Another way would be to rewrite your fetching functions like this:

function build_actor(post){
  return function (callback) {
    //query
    callback(null, actor);
  };
}

And use them like this:

async.series({ actor: build_actor(post) }, ...);

which would be even cleaner. Also note that if you can run the queries at the same time, async.parallel would work just as well.

Sign up to request clarification or add additional context in comments.

2 Comments

This is what i have wrote for actor, actor: function(callback){ build_actor(post, function(actor){ callback(null, actor); }); } I had to do callback(null, actor); instead of callback(actor); and it worked. Thanks! Cheers!
Ah yes you would have to do that when you don't follow the convention of passing an error as the first argument in a callback. I'll edit the post to suggest that the build_* functions are changed to callback(null, actor) to be more consistent with node standard practices.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.