0

I have a list of persons, each one contains a list of image urls.
I need to download each url, then calculate a 'signature' for that image, verify that it is unique, and then save it to file system.
My current approach is: two nested async.each calls, and one async.waterfall to check and save image (omitting error handling for simplicity): var async = require('async'); var request = require('request');

var syncPersonsImages = function(persons, images, callback) {
  async.each(
    persons,
    function(person, callbackPerson) {
      async.each(
        person.imageUrls,
        function(imageUrl, callbackImage) {
          download(imageUrl, function(err, image) {
            downloadPost(callbackImage);
          });
        },
        function(err) {
          callbackPerson();
        }
      );
    },
    function(err) {
      callback(null, persons);
    }
  );

  function download() {
    request(
      { uri: image.url },
      function(err) {
        callback(err, image);
      },
      function(contents, res) {
        image.contents = res.contents;
        callback(null, image);
      }
    );
  }

  function downloadPost(image, callback) {
    async.waterfall(
      [
        getSignatureFromImage,
        findSimilarSignatureImage,
        saveImage,
      ],
      function (err, image) {
        callback(image);
      }
    );
  }

  function getSignatureFromImage(image, callback) {
    image.signature = crypto.createHash('md5').update(image.url).digest('hex');
    callback(null, image);
  }

  function findSimilarSignatureImage(image, callback) {
    if (existsAlready(image.signature)) { // this function is not shown but it's behaviour is clear...
      image.isNew = true;
    }
    callback(null);
  }

  function save(image, callback) {
    if (image.isNew) {
      img.save(function(err) {
        console.log('image', image.url, 'saved');
        callback(null, image);
      }
    } else {
      callback(null, null);
    }   
  }

};

The problem is that the syncPersonsImages method never terminates...
Any suggestion?
Is my approach at least teoretically correct?

MarcoS
  • 17,323
  • 24
  • 96
  • 174
  • where is `download` defined? – Mike Atkins Dec 05 '15 at 01:31
  • @Mike Atkins: yes, sorry, forgot it... But the code was intended as 'pseudo-code', more than real code... However you're right... I'm going to completely rewrite the question with real working code... I was more interested in understanding if the presented flow is teoretically correct... – MarcoS Dec 05 '15 at 12:23

1 Answers1

1

Overall I think the approach is sound. A couple of points. I think you have unnecessarily wrapped some of your callbacks. For example, this:

  function(person, callbackPerson) {
    async.each(
      person.imageUrls,
      function(imageUrl, callbackImage) {
        download(imageUrl, function(err, image) {
          downloadPost(callbackImage);
        });
      },
      function(err) {
        callbackPerson();
      }
    );
  },
  function(err) {
    callback(null, persons);
  }
);

could be changed to:

function(person, callbackPerson) {
  async.each(
    person.imageUrls,
    function(imageUrl, callbackImage) {
      download(imageUrl, function(err, image) {
        downloadPost(callbackImage);
      });
    }, callbackPerson);
}, callback);

... depending on whether or not you want your async.each calls to bail the first time there is an error.

Also,you defined your download method without parameters.

Mike Atkins
  • 1,561
  • 13
  • 11