Ohad Ohad - 4 months ago 69
Node.js Question

Promisify aws streams

I want to download multiple files from S3 and once they all finish to download do something else.
I am using the following code to download the files:

function downloadFiles(folder, files) {

var params = {
Bucket: bucket
}

files.forEach(function (file) {
params.Key = folder + '/' + file;
var fileStream = fs.createWriteStream(config.s3_downloaded_files_folder + file);
S3.getObject(params).createReadStream().pipe(fileStream);
})
}


How do I promisify this code so I can execute some code once all files finished to download?

Thanks!

Answer

For streams, you can use the finish event to determine that the stream has finished. At this point, you can resolve the promise. You can create an array of promises for this:

Promise.all(files.map(file => new Promise((resolve, reject) => {
    const fileParams = Object.assign({Key: folder + "/" + file}, params);
    let fileStream = fs.createWriteStream(config.folder + file);
    S3.getObject(params).createReadStream().pipe(fileStream);
    file.on("finish", () => resolve());
    file.on("error", err => reject(err));
})));

Now you can chain .then to Promise.all which is resolved once all of the promises you have created are resolved.