0

I have a function in my helper js file to upload files on S3:

module.exports.uploadToAWS = function uploadToAWS(folderName, fileName, fileData) {

  var s3 = new AWS.S3({ params: {Bucket: ‘myBucket’} });

  var keyName = folderName + "/" + fileName;

  var buffer = new Buffer(fileData.replace(/^data:image\/\w+;base64,/, ""),'base64')

  var data = {
    Key: keyName, 
    Body: buffer,
    ContentEncoding: 'base64',
    ContentType: 'image/jpeg'
  };

  s3.putObject(data, function(err, data) {
    if (err) { 
      console.log(err);
      console.log('Error uploading data: ', data); 
    } else {
      console.log('succesfully uploaded the image!');
    }
  });
}

My consumer function is like this:

if(images) {
  images.forEach(function(imageRecord) {
    awsHelper.uploadToAWS('assets', assetObject.id, imageRecord);
  });            
}

I want to introduce a callback method here, such that I might get the success and failure from my helper function to my caller function. How could it be implemented? Need my consumer function to be like the following, but what would be the helper function be like?

if(images) {
  images.forEach(function(imageRecord) {
    awsHelper.uploadToAWS(
      'assets',
      assetObject.id,
      imageRecord,
      function (success, failure) {
        //handle success or failure
      });
  });
}
Nhan
  • 3,595
  • 6
  • 30
  • 38
Firdous
  • 4,624
  • 13
  • 41
  • 80
  • 1
    I would recommend against a consumer in that style, and instead recommend returning a Promise, so you can `doSomthingAsync().then(function(){}).catch(function(){})` instead. If that interests you, I could write a more involved answer. – spender Jun 23 '16 at 13:52
  • You mention `promise` but you're talking about callbacks. Did you prefer to return a promise somehow, or would a callback-only solution be okay? – Merlyn Morgan-Graham Jun 23 '16 at 13:54
  • Currently I just need a solution, new to javascript, just heard of promise, would definitely use it in future – Firdous Jun 23 '16 at 13:55
  • Promises are the way to go, especially now that they form a part of the `async/await` features in forthcoming ecmascript releases. – spender Jun 23 '16 at 13:59

3 Answers3

2

Why don't you simply add a Callback in your "uploadToAWS" like :

module.exports.uploadToAWS = function uploadToAWS(folderName, fileName, fileData, callback){

Then make a simple validation and call it (Passing the Response) when your upload completes/fails

s3.putObject(data, function(err, data){
      if (err) { 
        console.log(err);
        console.log('Error uploading data: ', data); 
        if(typeof callback === 'function') callback(err , data);
      } else {
        console.log('succesfully uploaded the image!');
        if(typeof callback === 'function') callback(err , data);
      }
    });

After this you will use it exactly as you proposed

if(images){
            images.forEach(function(imageRecord){
                awsHelper.uploadToAWS('assets', assetObject.id, imageRecord, function (err , data) {
                    //handle success or failure    
                });
            });            
        }
Strahdvonzar
  • 400
  • 2
  • 10
1

You need to pass the callback function as an argument for the helper function.

Try this:

module.exports.uploadToAWS = function uploadToAWS(folderName, fileName, fileData, callback){

    var s3 = new AWS.S3({ params: {Bucket: ‘myBucket’} });

    var keyName = folderName + "/" + fileName;

    var buffer = new Buffer(fileData.replace(/^data:image\/\w+;base64,/, ""),'base64')

    var data = {
        Key: keyName, 
        Body: buffer,
        ContentEncoding: 'base64',
        ContentType: 'image/jpeg'
    };

    s3.putObject(data, function(err, data){
       if (err) { 
         callback(err);
       } else {
         callback(null, data);
       }
    });
}
Shiva
  • 56
  • 3
1

So by rewriting in the Promise style, you can:

module.exports.uploadToAWSAsync = 
    function uploadToAWSAsync(folderName, fileName, fileData){
        return new Promise(function(resolve, reject){
            var s3 = new AWS.S3({ params: {Bucket: ‘myBucket’} });

            var keyName = folderName + "/" + fileName;

            var buffer = new Buffer(fileData.replace(/^data:image\/\w+;base64,/, ""),
                                    'base64')

            var data = {
                    Key: keyName, 
                    Body: buffer,
                    ContentEncoding: 'base64',
                    ContentType: 'image/jpeg'
                };

            s3.putObject(data, function(err, data){
                  if (err) { 
                    console.log(err);
                    console.log('Error uploading data: ', data); 
                    reject(err);
                  } else {
                    console.log('succesfully uploaded the image!');
                    resolve();
                  }
                });
        });
    }

You could rewrite you consumer code as follows:

//fire them all off in one go
var promises = images.map(function(imageRecord){
    return awsHelper.uploadToAWSAsync('assets', assetObject.id, imageRecord);
}); 
Promise.all(promises).then(function(){
    //success, everything uploaded
}).catch(function(err){
    //something went wrong
});
spender
  • 117,338
  • 33
  • 229
  • 351