17

I have been using the code below (which I have now added await to) to send files to S3. It has worked fine with my lambda code but as I move to transfer larger files like MP4 I feel I need async/await.

How can I fully convert this to async/await?

exports.handler = async (event, context, callback) => {
...
// Copy data to a variable to enable write to S3 Bucket
var result = response.audioContent;
console.log('Result contents ', result);

// Set S3 bucket details and put MP3 file into S3 bucket from tmp
var s3 = new AWS.S3();
await var params = {
Bucket: 'bucketname',
Key: filename + ".txt",
ACL: 'public-read',
Body: result
};

await s3.putObject(params, function (err, result) {
if (err) console.log('TXT file not sent to S3 - FAILED'); // an error occurred
else console.log('TXT file sent to S3 - SUCCESS');    // successful response
context.succeed('TXT file has been sent to S3');
});
1
  • 2
    You don't need to use await var params = ... await is only useful for promises Commented Mar 5, 2019 at 22:35

2 Answers 2

36

You only await functions that return a promise. s3.putObject does not return a promise (similar to most functions that take a callback). It returns a Request object. If you want to use async/await, you need to chain the .promise() method onto the end of your s3.putObject call and remove the callback (https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html#promise-property)

try { // You should always catch your errors when using async/await
  const s3Response = await s3.putObject(params).promise();
  callback(null, s3Response);
} catch (e) {
  console.log(e);
  callback(e);
}
Sign up to request clarification or add additional context in comments.

4 Comments

I think this is right on track, except you probably also don't want to use the deprecated context.succeed() here, since that's mixing async/await and callbacks. Return a response or a promise, since you're inside an async function (the handler), yes?
What should context.succeed(s3Response); be replaced with in an async/await situation?
Perhaps callback(null, s3Response);?
Yes, I wasn't sure about the context.succeed. I did a little research, and the context object is really just to provide additional information about the lambda request (docs.aws.amazon.com/lambda/latest/dg/…). Instead of context.succeed you want to call callback(null, s3Response). I'll update my answer
9

As @djheru said, Async/Await only works with functions that return promises. I would recommend creating a simple wrapper function to assist with this problem.

const putObjectWrapper = (params) => {
  return new Promise((resolve, reject) => {
    s3.putObject(params, function (err, result) {
      if(err) reject(err);
      if(result) resolve(result);
    });
  })
}

Then you could use it like this:

const result = await putObjectWrapper(params);

Here is a really great resource on Promises and Async/Await:

https://javascript.info/async

1 Comment

i guess small change needed if(err) resolve(err); should be replaced by if(err) reject(err);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.