title: Combine sequence of asynchronous requests to build final answer
body: <p>I'm rather new in express framework. I have call flickr api to get albums list and for each album need to get its thumbnail. On the end need to build <code>covers</code> array with list of objects like <code>{title, thumb}</code>. I would like to pass fully created <code>covers</code> array to template and render. I have problem with it because of the way that node.js callbacks works and <em>for loop</em> ends quickly before requests ends. How to do that properly ?</p>
  
  <pre><code>http.get(base_url+'&amp;user_id='+flickr.user_id+'&amp;method=flickr.photosets.getList', function(resp){
      var body = '';
      resp.on('data', function(chunk) {
          body += chunk;
      });
      resp.on('end', function() {
          var json = JSON.parse(body);
          var ps = json.photosets.photoset;
  
          // final answer
          var covers = {};
  
          for(var i=0; i&lt;ps.length; i++) {
              var p = ps[i];
              var getSizesUrl = base_url+'&amp;user_id='+flickr.user_id+'&amp;method=flickr.photos.getSizes&amp;photo_id='+p.primary;
              http.get(getSizesUrl, function(resp){
                  var body1 = '';
                  resp.on('data', function(chunk) {
                      body1 += chunk;
                  });
                  resp.on('end', function() {
                      var json1 = JSON.parse(body1);
                      covers += {title: p.title._content, thumb: json1.sizes.size[1].source};
  
                     if(i + 1 == ps.length) {
                          // last call
                          console.log(covers);
                          res.render('photosets', {covers: covers});
                      }
                  });
              });
          }
      });
  });
  </code></pre>
  
  <p>Update using <code>async</code> and <code>request</code> as @sgwilly said, but something wrong... </p>
  
  <pre><code>request(base_url+'&amp;user_id='+flickr.user_id+'&amp;method=flickr.photosets.getList', function (error, response, body) {
      var json = JSON.parse(body);
      var ps = json.photosets.photoset;
  
      // functions list to call by `async`
      var funcs = {};
  
      for(var i = 0; i &lt; ps.length; i++) {
          var p = ps[i];
          funcs += function(callback) {
              request(base_url+'&amp;user_id='+flickr.user_id+'&amp;method=flickr.photos.getSizes&amp;photo_id='+p.primary, function (error, response, body1){
                  var json1 = JSON.parse(body1);
                  var cover = {title: p.title._content, thumb: json1.sizes.size[1].source};
                  callback(null, cover);
              });         
          };
      }
  
      // run requests and produce covers
      async.series(funcs,
          function(covers){
              console.log(covers);
              res.render('photosets', {covers: covers});              
          }
      );
  
  });
  </code></pre>