8

Building my first "serious" Node.js project (using Express).

I need to use several calls to several REST APIs, collect all the results, massage them and return a complete JSON to the client (HTML5 + AJAX).

  1. Call API A
  2. Call API B
  3. Call API A again (with results from B)
  4. Process results from the 3 calls into a JSON
  5. response.send(result)

I'm sure/hoping there's an easy pattern, or solution, or module that I just didn't google properly for :) I'd also would appreciate an opinion on where to place such operations (under 'routes'? Seperate files? etc.)

Thanks for your time!

5
  • this is just a general asynchronous programming question. I don't think it's well suited to stackoverflow because there are many, many different ways to address it (fibers, async libraries, event handling). You should just uses promises with the awfully named but very useful Q library. This is an opinionated answer so I'm leaving it as a comment. I hope to see this question closed NOW. Commented Sep 10, 2012 at 5:10
  • 5
    @AndyRay It's a good thing that you can not yet close questions. Commented Sep 10, 2012 at 5:16
  • @AndyRay There's no rule against asking general questions. I'm seeking the best tools as I'm learning my way on how to node right. If you do have an answer, leave it as one - I'd be glad to learn more about each of the solutions you offered, and you may get some points. Closing a question because you already know the answer to it beats the purpose of this entire site :) Commented Sep 10, 2012 at 5:33
  • I think this is better suited for the nodejs mailing list groups.google.com/forum/?fromgroups#!forum/nodejs it seems too open ended to be on SO Commented Sep 10, 2012 at 5:46
  • 3
    @Andy An "open-ended" question requires to accumulate at least a few answers, right? I see none so far. Also, this question is not about "the best way to do it" but "a way to do it". I don't see how this could not be a fit for SO's format; I really don't get your point. Besides, commenting with "I hope this gets closed NOW" is not only not very nice. Trying to influence people to close a question because you don't like it is also not how community-based closing is supposed to work. Commented Sep 10, 2012 at 5:58

2 Answers 2

8

The async module fits into this kind of job. Specifically, you may use the async.waterfall function.

Example:

async.waterfall([
    function(callback){
        callback(null, 'one', 'two');
    },
    function(arg1, arg2, callback){
        callback(null, 'three');
    },
    function(arg1, callback){
        // arg1 now equals 'three'
        callback(null, 'done');
    }
], function (err, result) {
   // result now equals 'done'    
});

Edit, if you have some nontrivial dependencies between the jobs, then you may use async.auto. It will determine the best order for running functions based on their requirements.

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

4 Comments

+1 I was writing the same answer (you beat me to it). The one thing that's missing is an indication how to get all the results from 1, 2 and 3 into step 4.
Seems like what I was looking for. One question though: would I be able to combine .waterfall with .parallel? I.e. parallell all calls and waterfall the ones that depend on each other? I have more than 3 calls, with some interesting dependencies...
@TravelingTechGuy Then you may use async.auto
Thanks, this thread helped me a lot, as I was looking for a chaining solution other than promises in Node
2

There are a lot of control flow libraries around. I've used Q in my previous projects which I have no complaints about, however I'll probably look into using the async library by caolan for my next project.

https://github.com/caolan/async

From what you've described above, you'd probably want to look at using the parallel function

https://github.com/caolan/async#parallel

The problem you describe can be pretty easily transferred to the parallel example in the docs

EDIT: I missed the bit about API calls being dependent. Whenever you need to pass values along the chain and control the order you'd need to use the waterfall method (see qiao's answer). If there is a case where the calls are independent, you'd use the parallel method. An example of the parallel method is below

async.parallel({
    google: function(callback){
      http.get("http://www.google.com", function(res){
        console.log("google done");
        callback(null, res.statusCode);
      })
    },
    yahoo: function(callback){
      http.get("http://www.yahoo.com", function(res){
        console.log("yahoo done");
        callback(null, res.statusCode);
      })    
    }
  },
  function(err, results) {
    if(!err){
      console.log("all done");
      console.log(results.google);
      console.log(results.yahoo);
    }else{
      console.log(err);
    }
  }
);

What this does is makes all your requests in parallel and gives you a callback when they are all done. This is where you would massage your data.

List of control flow libraries:

https://github.com/joyent/node/wiki/Modules#wiki-async-flow

3 Comments

parallel() won't work because a) it won't execute the steps in a defined sequence and b) there is no way to pass along a result from one function to the next.
Thanks, missed that. Edited my answer
It's not only about the order. It's also about passing results from one step to another. parallel() just is not right for that.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.