Search code examples
node.jsasynchronousnode-async

Async and parallel functions in nodejs


I get and issue using parallel() function in Async module...

The array images is empty...

var asyncTasks = [];

switch(type){
  case 'instafilm':

    var newFileName;
    var images = [];

    selectedPhotos.forEach(function(id){
      newFileName = pathDir + '/' + id + '.jpg';
      asyncTasks.push(function(callback){
        self.api.media(id, function(err, media, remaining, limit) {
          images.push(media.images.thumbnail.url);
        });
      });
    });

    asyncTasks.push( function(callback){
      console.log(images); // empty
    });


    break;
}

console.log(images); // empty

EDIT #1 :

var asyncTasks = [];

var newFileName;
var images = [];

selectedPhotos.forEach(function(id){
  newFileName = pathDir + '/' + id + '.jpg';
  asyncTasks.push(function(callback){
    self.api.media(id, function(err, media, remaining, limit) {
      images.push(media.images.thumbnail.url);
      callback(null);
    });
  });
});

asyncTasks.push( function(callback){
  console.log(images); // before creating .zip I need to write files using images[]
  gm()
  .in('-page', '+0+0')
  .in('./public/images/instafilm.jpg')
  .in('-page', '+10+10')
  .in(images[0])
  .in('-page', '+10+30')
  .in(images[1])
  .in('-page', '+10+60')
  .in(images[2])
  .in('-page', '+10+90')
  .in(images[3])
  .mosaic()
  .minify()
  .write(newFileName, function (err) {
    if (!err) console.log('done');
    if (err) console.log(err);
    callback();
  });
});



async.parallel(asyncTasks, function(){
    // here I write a .zip file
    var admZip = new AdmZip();
    var pathDir = './public/uploads/'+reference;
    admZip.addLocalFolder(pathDir);
    var willSendthis = admZip.toBuffer();
    admZip.writeZip('./public/uploads/'+reference+'.zip');   
});


Solution

  • If I understand your snippet right, your callback function is never called in :

    self.api.media(id, function(err, media, remaining, limit) {
      images.push(media.images.thumbnail.url);
    });
    

    which is a problem.

    Another issue I can think of is that you call console.log(images) just after executing this snippet (so async code have not been executed yet) and as a part of your parallel call. But parallel as it's name implies (and it's doc confirm) run your tasks "parallel" (as much as node allows it).

    So, especially since console.log() is synchronous, your media([...]) call wouldn't have time to finish before the console call.

    If I guess right, you then need to add a callback like this :

    function(callback){
      self.api.media(id, function(err, media, remaining, limit) {
        images.push(media.images.thumbnail.url);
        callback(null);
      });
    }
    

    And to check images content after your async code finish like :

    parallel(asyncTasks,function(){
      console.log(images)
    })
    

    Edit : According to new code snippet :

    first part of the code look OK, until gm call wich should be done as this :

    async.parallel(asyncTasks, function(){
      gm()
      .in('-page', '+0+0')
      .in('./public/images/instafilm.jpg')
      .in('-page', '+10+10')
      .in(images[0])
      .in('-page', '+10+30')
      .in(images[1])
      .in('-page', '+10+60')
      .in(images[2])
      .in('-page', '+10+90')
      .in(images[3])
      .mosaic()
      .minify()
      .write(newFileName, function (err) {
        if (!err) console.log('done');
        if (err) console.log(err);
        // here I write a .zip file
        var admZip = new AdmZip();
        var pathDir = './public/uploads/'+reference;
        admZip.addLocalFolder(pathDir);
        var willSendthis = admZip.toBuffer();
        admZip.writeZip('./public/uploads/'+reference+'.zip');   
      });
    });