Barney
Barney

Reputation: 915

What's the right way to return from an AWS Lambda function in Node.js?

I am new to AWS Lambda and there is one thing I find very confusing.

So far, I found following options how to return from a function in Node.js:

1.

exports.handler = (event, context) => {
    context.succeed('ok');
}

2.

exports.handler = (event, context) => {
    context.done(null, 'ok');
}

3.

exports.handler = (event, context, callback) => {
    callback(null, 'ok');
}

4.

exports.handler = async event => {
    return "ok";
}

How are these different? Any functionality or performance distinctions?

Can anyone explain how to terminate a function in the right way?

Upvotes: 26

Views: 18230

Answers (1)

ttulka
ttulka

Reputation: 10892

You're probably using Node.js 8.10, which is so far the last Node.js version supported by AWS Lambda, otherwise the last (4.) snippet woudn't work at all (due to a syntax error).

In Node.js 8.10 all the above listed variants are valid, most of them are still there only for compatibility with earlier runtime versions.

The fist two (1. and 2.) are the oldest ones and it's not recomended to use them anymore. The done(err?, res?) function is an equivalent to the later added callback(err?, res?), which was frequently used before Node.js 8.10 and you can still find a lot of code examples even in the official documentation. It's a typical callback and could be used in asynchronous processing:

exports.handler = (event, context, callback) => {
    var params = {
        Bucket: "examplebucket", 
        Key: "HappyFace.jpg"
    };
    s3.getObject(params, function(err, data) {
        if (err) return callback(err);
        callback(null, data);
    });    
}

Nevertheless, this function has all the drawbacks of using callbacks in general (Callback Hell).

Up Node.js 8.10 you can use Promises together with async/await syntactic sugar, which makes asynchronous computation look like synchronous. AWS JavaScript SDK added a function promise() to almost all the functions previously using callbacks. Now you can write:

exports.handler = async event => {
    var params = {
        Bucket: "examplebucket", 
        Key: "HappyFace.jpg"
    };
    var data = await s3.getObject(params).promise();
    // here you process the already resolved data...
    return data;

    // or you can omit `await` here whatsoever:
    // return s3.getObject(params).promise();
}

Which produces shorter and eleganter code, more readable for humans.

Of course, at the end you can choose what you like, just compare your example snippets...

Upvotes: 27

Related Questions