Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to upload files to s3 synchronously using node.js api

I have the following piece of code:

array.forEach(function (item) {

       // *** some processing on each item ***

        var params = {Key: item.id, Body: item.body};
        s3bucket.upload(params, function(err, data) {
            if (err) {
              console.log("Error uploading data. ", err);
            } else {
              console.log("Success uploading data");
        }});
  });

Because s3bucket.upload is being executed asynchronously - the loop finishes before uploading all the items.

How can I force s3bucket.upload to be synchronous?

Meaning don't jump to next iteration until this item was uploaded (or failed) to S3.

Thanks

like image 997
belostoky Avatar asked Jan 17 '16 15:01

belostoky


3 Answers

you can use https://github.com/caolan/async#each each or eachSeries

function upload(array, next) {
    async.eachSeries(array, function(item, cb) {
        var params = {Key: item.id, Body: item.body};
        s3bucket.upload(params, function(err, data) {
            if (err) {
              console.log("Error uploading data. ", err);
              cb(err)
            } else {
              console.log("Success uploading data");
              cb()
            }
        })
    }, function(err) {
        if (err) console.log('one of the uploads failed')
        else console.log('all files uploaded')
        next(err)
    })
}
like image 136
Krishna Srinivas Avatar answered Oct 17 '22 23:10

Krishna Srinivas


Better to use promises as suggested in one of the comments:

const uploadToS3 = async (items) => {
  for (const item of array) {
    const params = { Key: item.id, Body: item.body };
    try {
      const data = await s3bucket.upload(params).promise();
      console.log("Success uploading data");
    } catch (err) {
      console.log("Error uploading data. ", err);
    }
  }
}
like image 25
Erez Avatar answered Oct 17 '22 22:10

Erez


You could pass a post back function, this way the rest of the code is executed only when the upload has been completed. This does not answer your question but could be an alternative option:

array.forEach(function (item) {

   // *** some processing on each item ***

    var params = {Key: item.id, Body: item.body};
    var f1=function(){
       // stuff to do when upload is ok!
     }
      var f2=function(){
       // stuff to do when upload fails
     }
    s3bucket.upload(params, function(err, data) {

        if (err) {
         f2();
          console.log("Error uploading data. ", err);
         // run my function

        } else {
       // run my function
          f1();
          console.log("Success uploading data");
    }});

  });
like image 2
Marck Duilberg Avatar answered Oct 17 '22 22:10

Marck Duilberg