I am trying to get a list of objects out of an S3 bucket and when I have a list of objects I would like to generate pre-signed URLs for these objects. The only way I could figure out how to do this was to use nested callback functions like so:
exports.handler = async (event, context, callback) => {
console.log('processing event: %j', event);
const bucket = process.env['s3_bucket'];
if (!bucket) {
callback(new Error("s3 bucket not set"));
}
const deviceId = event['deviceId'];
const params = getListObjectsParams(deviceId, bucket);
let count = 0;
await s3.listObjectsV2(params, function (err, data) {
if (err) callback("Error getting image list: " + err);
else {
data.Contents.forEach(function (image) {
count = count + 1;
const objectParams = getObjectParams(bucket, image.Key);
s3.getSignedUrl('getObject', objectParams, function (err, url) {
if (err) {
console.log("Error");
console.log(err);
//TODO: log error getting pre signed url
} else {
images.push(url);
}
});
});
}
});
callback(null, images);
};
I am having some trouble returning the images array as the function is completing before the calls to listObjectsV2 and each of the getSignedUrl complete. Here are my questions.
- How do I get the execution to wait for promises to complete before completing executing the function?
- If there a better way to layout this block of code, nesting callbacks look messy :(