AWS Lambda using s3 getObject function nothing happening

12,365

The call to s3.getObject is an asynchronous call. The execution of the code continues while the s3 code is run. You need to explicitly await for the call's promise to resolve.

This is how you would do that (note the change in the s3.getObject call):

const AWS = require('aws-sdk');
const s3 = new AWS.S3();

exports.handler = async (event) => {
    var params = { 
        Bucket: <bucket>,
        Key: <key>,
    };

    const data = await s3.getObject(params).promise();

    const response = {
        statusCode: 200,
        body: JSON.stringify(data),
    };
    return response;
};

You can use a try/catch block for error handling.

The important thing to understand here is the timing of the execution. The mainline code in your function is called sequentially when the lambda is invoked. The callback function that you pass to the s3.getObject call is called when a response from S3 arrives, long after your lambda had finished its execution.

Your return call is executed before the callback runs, and hence you see the result of JSON.strigify(responseMsg) where responseMsg holds the initial value you gave it, which is the empty string ''.

Share:
12,365
BermudaLamb
Author by

BermudaLamb

Senior-level Information Technology Architect with solid experience in strategic planning, project management, and enterprise-wide systems architecture. Successful background of leveraging existing technologies and systems to increase comipetitive advantage, and the introduction of new technologies to improve productivity while reducing workflow bottle-necks. Able to translate abstract concepts into practical, feature-rich solutions. Proven track record of developing, implementing and converting to ERP and CRM systems.

Updated on June 14, 2022

Comments

  • BermudaLamb
    BermudaLamb almost 2 years

    This is the node.js code using the inline editor:

    const AWS = require('aws-sdk');
    const s3 = new AWS.S3();
    
    console.log('Loading function');
    
    exports.handler = async (event) => {
        // TODO implement
        var responseMsg = '';
        var bucket = '';
        var key = '';
        if ('Records' in event) {
            var s3Data = event.Records[0].s3;
            console.log('s3Data: ' + JSON.stringify(s3Data));
            bucket = s3Data.bucket.name;
            key = s3Data.object.key;
        }
        console.log('Bucket:' + bucket);
        console.log('Key:' + key);
        var params = { 
            Bucket: bucket,
            Key: key
        };
        console.log('Params:' + JSON.stringify(params));
        s3.getObject(params, function (err, data) {
           console.log('getObject');
           if (err) {
               console.log(err, err.stack);
               return err;
           } 
           responseMsg = data;
        });
        const response = {
            statusCode: 200,
            body: JSON.stringify(responseMsg),
        };
        return response;
    };
    

    I know that the key and bucket I'm testing with exists in my S3 console. I know that I can access the them using C# in LINQPad.

    When I run this, I'm not getting any errors. I'm getting an empty string in the body of response, rather than the content of the object. I'm also not getting any log messages from within the s3.getObject.

  • muasif80
    muasif80 over 3 years
    How to handle multiple getobject requests in lambda like this.?
  • muasif80
    muasif80 over 3 years
    Ok so I was trying to use forEach to loop through the keys and calling getobject but it did not work as it involves a callback function. Although simple for-loop has worked in doing multiple getobject calls and then collecting their results into an array
  • Kalev
    Kalev over 3 years
    Yeah, a forEach won't work (at least not the naive approach). What I'd do instead is use Array.map() to produce a list of promises, and use Promise.all() on the resulting list of promises.
  • muasif80
    muasif80 over 3 years
    Ok. This Promise.all i tried but may be missing something it also did not work. Will check it again sometime. Thanks.