Skip to content

Instantly share code, notes, and snippets.

@tarasowski
Last active July 22, 2023 04:47
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tarasowski/ccc2158c075c49576d8ba321b338d7be to your computer and use it in GitHub Desktop.
Save tarasowski/ccc2158c075c49576d8ba321b338d7be to your computer and use it in GitHub Desktop.
#Lambda - Async/Await Rules
  1. The function after await someFunc() need to return a promise. Otherwise it will not await and exit from the function. The function below will simply exit and won't wait till the background process is finished. Since async functions are waiting for Promises. The keyword await makes JavaScript wait until that promise settles and returns its result.
const hello4 = () => setTimeout(() => console.log('Hello from Hello4'), 5000)

const asycFunc = async() => {
	await hello4()
    return
}

But if do return a promise:

const hello4 = () => {
    return new Promise(resolve => {
        setTimeout(() => resolve(console.log('Hello from Hello4')), 2000)
    })
}

const asycFunc = async() => {
	await hello4()
    return
}

// Hello from Hello4
  1. If something doesn't return a promise you need to promisify it. For instance, you can promisify the Amazon SDK by adding .promise(). So you can use async/await functions. The AWS.Request.promise method provides a way to call a service operation and manage asynchronous flow instead of using callbacks.
var s3 = new AWS.S3({apiVersion: '2006-03-01', region: 'us-west-2'});
var params = {
  Bucket: 'bucket',
  Key: 'example2.txt',
  Body: 'Uploaded text using the promise-based method!'
};
var putObjectPromise = s3.putObject(params).promise();
putObjectPromise.then(function(data) {
  console.log('Success');
}).catch(function(err) {
  console.log(err);
});
  1. Use try{} catch (error) {} to do proper error handling
const hello4 = () => {
    return new Promise(resolve => {
        setTimeout(() => resolve(console.log('Hello from Hello4')), 2000)
    })
}

const asycFunc = async() => {
	try {
    await hello4()
    return
    }
    catch (error) {
	console.log(error)
    }
}

// Hello from Hello4

Note: An async function can contain an await expression that pauses the execution of the async function and waits for the passed Promise's resolution, and then resumes the async function's execution and returns the resolved value. The return value of an async function is implicitly wrapped in Promise.resolve.

Below you can see an example how async and sync operations can be mixed together.

const AWS = require('aws-sdk');

exports.handler = async function(event, context, callback) {
    const EC2 = new AWS.EC2();
    const S3 = new AWS.S3();

    try {
        // Get some info about all instances.
        const instancesData = await EC2.describeInstances().promise();

        // Get instance IDs.
        const instanceIds = [];
        instancesData.Reservations.forEach(reservation => {
            reservation.Instances.forEach(instance => {
                instanceIds.push(instance.InstanceId);
            });
        });

        // Iterate through each instance ID.
        for (instanceId of instanceIds) {
            // Create an S3 bucket.
            await S3.createBucket({ Bucket: instanceId }).promise();

            // Put an object into the newly created bucket.
            await S3.putObject({ Bucket: bucketId, Key: 'hello.txt', Body: 'Hello world!' }).promise();
        }

        callback(null, 'Success!');
    } catch (err) {
        callback(err.message);
    }
};

Using Await/Async

If you want don't want to use callback(null, 'success) inside an async/await function you need always to include try{}catch (err) {}. Therefore there will be no need to include callback, see example below:

exports.lambda_handler = async(event, context, callback) => {
    try {
    	await dynamodb.putItem(params).promise()
        return 'Works' // return a message a success message to the caller
    }
    catch (error) {
    	console.log(error)
        return 'Error' // return an error to the caller
    }
}

Returning a Promise

If you don't use async/await lambda function you can exit the function by simply returing a promise that will be either resolved or rejected. Based on the resolution the caller will get the right message, see example below:

exports.handler = (event) => {
    
    let params = {
        TableName: TABLE_NAME
    }
    
    return dynamoDb.scan(params)
    .promise()
    .then(response => (processResponse(IS_CORS, response.Items)))
    .catch(err => {
        console.log(err);
        return processResponse(IS_CORS, 'dynamo-error', 500);
    })
}


// inside processResponse()

module.exports = (isCors, body, requestedCode) => {
    const code = requestedCode || (body ? 200 : 204);
    const headers = isCors ? {
        'Access-Control-Allow-Headers': 'Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token',
        'Access-Control-Allow-Methods': 'OPTIONS,POST',
        'Access-Control-Allow-Origin': process.env.CORS_ORIGIN,
        'Access-Control-Max-Age': '86400',
        'Content-Type': 'application/json'
    } : { 'Content-Type': 'application/json' };
    return {
        statusCode: code,
        body: JSON.stringify(body) || '',
        headers: headers
    };
};

Using the Callback Parameter

The Node.js runtimes v6.10 and v8.10 support the optional callback parameter. You can use it to explicitly return information back to the caller. If you don't use callback in your code, AWS Lambda will call it implicitly and the return value is null. When the callback is called (explicitly or implicitly), AWS Lambda continues the Lambda function invocation until the event loop is empty.

exports.myHandler = function(event, context, callback) {
   console.log("value1 = " + event.key1);
   console.log("value2 = " + event.key2);  
   callback(null, "some success message");
   // or 
   // callback("some error type"); 
}
@NguyenKyThinh94
Copy link

This is a huge magic, i must take 3 days and it still not run correctly :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment