2

I'm using a lambda function in AWS to do some work and I need the function get some data from the AWS SSM resource in order to complete the work. However I'm struggling to get the code to wait for the call to getParameter to wait until the call back has completed prior to moving on.

I've tried structuring the code in two different ways.

Structure reference #1

Structure reference #2

Neither way seems to get the execution to pause.

With my current implementation which is built on "Structure reference #2" I'm not sure what I'm doing wrong.

const aws = require('aws-sdk');
const crypto = require('crypto');
const ssm = new aws.SSM();

exports.handler = async (event, context, callback) => {

console.log(event.headers);

var webhook = JSON.parse(event.body);
var key = "";

var parameterRequest = ssm.getParameter( {
 Name: "param1",
 WithDecryption: true
}, function(err, data) {
    if (err)
    {
        console.log(err);    
    }
    else
    {
        key=data.Parameter.Value;    
        console.log(data);
    }
});

await parameterRequest;

var hash = crypto.createHmac('sha1', key).update(JSON.stringify(webhook)).digest('hex');
console.log("HASH: sha1=" + hash);
console.log("Key:" + key);
}

const response = {
        "statusCode": 200,
        "statusDescription": "200 OK"
    };
    return callback(null, response);

Why would the console.log("HASH: sha1=" + hash); and console.log("Key:" + key); get executed prior to the console.log(data);?

Update 7/2/2019

Await and Promise applied without the try catch:

const aws = require('aws-sdk');
const crypto = require('crypto');
const ssm = new aws.SSM();

exports.handler = async (event, context, callback) => {

console.log(event.headers);

var webhook = JSON.parse(event.body);
var key = "";

var parameterRequest = await ssm.getParameter( {
 Name: "param1",
 WithDecryption: true
}, function(err, data) {
    if (err)
    {
        console.log(err);    
    }
    else
    {
        key=data.Parameter.Value;    
        console.log(data);
    }
}).promise();

var hash = crypto.createHmac('sha1', key).update(JSON.stringify(webhook)).digest('hex');
console.log("HASH: sha1=" + hash);
console.log("Key:" + key);
}

const response = {
        "statusCode": 200,
        "statusDescription": "200 OK"
    };
    return callback(null, response);
Aaron
  • 511
  • 3
  • 25
  • `await` only does something useful when you await a promise. It has no magic powers to make something else wait. It seems likely your function does not return a promise so `await` doesn't do anything. Either wrap your own promise around the interface and find out how to get a promise out of the interface you have. – jfriend00 Jul 02 '19 at 03:07
  • Ref https://stackoverflow.com/questions/51328292/how-to-use-async-and-await-with-aws-sdk-javascript/51328537#51328537 – hoangdv Jul 02 '19 at 03:07

1 Answers1

3

SSM.getParameter does not return Promise directly, it returns an AWS.Request. You can use AWS.Request.promise() to consume the request as a promise.

try {
    const data = await ssm.getParameter({
        Name: "param1",
        WithDecryption: true
    }).promise();
    console.log(data);

    const key = data.Parameter.Value;
} catch (err) {
    console.log(err);
}
Jake Holzinger
  • 5,783
  • 2
  • 19
  • 33
  • That works well to make it a serialized flow. I applied the await and promise changes to my original code and the log statement for the key got fired twice. Do you happen to know why that would happen? – Aaron Jul 02 '19 at 15:54
  • The log statement should not fire more than once, I can't say for sure without seeing your new code though. – Jake Holzinger Jul 02 '19 at 17:55
  • I updated the post with the new code by adding the await and promise. – Aaron Jul 02 '19 at 17:58
  • 1
    You shouldn't use the callback if you're using promises, the AWS client likely calls the callback *AND* resolves the promise. You should omit the callback in favor of try/catch and consume the data from the `parameterRequest` variable. – Jake Holzinger Jul 02 '19 at 18:12