使用Async / Await从DynamoDB检索数据时,Lambda函数未调用Https.request函数

时间:2019-04-30 12:10:08

标签: amazon-web-services async-await aws-lambda amazon-dynamodb

在AWS- Lambda中,我正在打电话从DynamoDB表中检索数据,并使用该数据向API Gateway发出发布请求。 我使用Async / await从DynamoDB检索数据。但是,在向API网关发出发布请求时,未调用 Https.request

我是NodeJs和Lambda的新手,感谢您的帮助以获取解决方案。

我尝试实现Promise时没有任何运气。如果我删除Async / await,则Https.request调用将正常工作而没有任何问题。但是数据无法用于https.request进行发布请求(由于异步调用)。

// Dynamo DB Params
var {promisify} = require('util');
var AWS = require('aws-sdk');
var dynamoDB  = new AWS.DynamoDB.DocumentClient();
var dynamoDBGetAsync = promisify(dynamoDB.get).bind(dynamoDB );
var https = require('https');

exports.handler = async function(event,context) {
    let probID = JSON.stringify(event.ID);
    probID = probID.replace(/"/g, '');      

    let params = {
        TableName : '<dummy_table>',
        Key:{
            'Server':<serverid>,
            'Service':'process2'
        }
    };

    //fetching the details from Dynamo DB 
    var dataResult= await dynamoDBGetAsync(params);   

    var obj;   
    var message = 'Sample Message';
    functionCall(dataResult,callback => {
        obj = JSON.parse(callback);
    });
}

function functionCall(data,result) {
// Options and headers for the HTTP request
    var options = {
        host: 'dummy.execute-api.us-east-1.amazonaws.com',
        port: 443,
        path: '/dev/test',
        method: 'POST',
        headers: {
            'Accept':'*/*',
            'cache-control':'no-cache',
            'Content-Type': 'application/json'
        }
    };
    const body= "{\"msg\": "+ data + "\"}";
    console.log('BODY.....:'+body);      //able to see this comment in console

    let req = https.request(options, (res) => {     // This is not getting invoked and cannot see below comment in console
        console.log('IN HTTPS REQUEST.....');
        var responseString = '';
        console.log("statusCode:" + res.statusCode);

        res.setEncoding('UTF-8');
        // Collect response data as it comes back.
        res.on('data', function(data) {
            responseString += data;

        });

        res.on('end', function() {
            result(responseString);
        });
    });

    // Handler for HTTP request errors.
    req.on('error', function(e) {
        console.error('HTTP error: ' + e.message);
        result('Request completed with error(s).');
    });

    req.write(body);
    req.end();
}

1 个答案:

答案 0 :(得分:1)

可能有一些问题,但最令我惊讶的是,您错误地混合了编程样式。

您已将处理程序声明为异步函数,这很好。但是在异步函数内部,您正在将一个等待的调用与您没有适当等待的经典延续样式函数调用混合在一起。

发生的事情是,您的Lambda执行了第一部分(对dynamo的调用),然后运行库在实际完成第二个延续样式函数调用之前结束了执行。

一种解决方案是将您的https请求包装在promise中,然后在Lambda处理程序的主体中等待它:

// Dynamo DB Params
const {promisify} = require('util');
const AWS = require('aws-sdk');
const dynamoDB  = new AWS.DynamoDB.DocumentClient();
const dynamoDBGetAsync = promisify(dynamoDB.get).bind(dynamoDB );
const https = require('https');

exports.handler = async function(event,context) {
    let probID = JSON.stringify(event.ID);
    probID = probID.replace(/"/g, '');      

    let params = {
        TableName : '<dummy_table>',
        Key:{
            'Server':<serverid>,
            'Service':'process2'
        }
    };

    //fetching the details from Dynamo DB 
    let dataResult= await dynamoDBGetAsync(params);   

    const message = 'Sample Message';
    let jsonResult = await functionCall(dataResult);
    let obj = JSON.parse(jsonResult);
    // presumably you want to return something here (not sure if obj or something else)
    return obj;
}

function functionCall(data) {
    // Options and headers for the HTTP request
    const options = {
        host: 'dummy.execute-api.us-east-1.amazonaws.com',
        port: 443,
        path: '/dev/test',
        method: 'POST',
        headers: {
            'Accept':'*/*',
            'cache-control':'no-cache',
            'Content-Type': 'application/json'
        }
    };
    const body= "{\"msg\": "+ data + "\"}";
    console.log('BODY.....:'+body);

    // make this function awaitable by returning a promise
    return new Promise((resolve, reject) => {
      let req = https.request(options, (res) => {
        console.log('IN HTTPS REQUEST.....');
        let responseString = '';
        console.log("statusCode:" + res.statusCode);

        res.setEncoding('UTF-8');
        // Collect response data as it comes back.
        res.on('data', function(data) {
          responseString += data;
        });

        res.on('end', function() {
          // complete the promise successfully
          resolve(responseString);
        });
      });

      req.on('error', function(e) {
        console.error('HTTP error: ' + e.message);
        // complete the promise with error (will throw if awaited)
        reject('Request completed with error(s).');
      });

      req.write(body);
      req.end();
    });
}

顺便说一句-使用async / await,您真的不需要 promisify 来使用DynamoDB。 DynamoDB客户端内置了对您可以等待的承诺的支持。只需在您的操作上致电.promise(),然后等待即可。例如,您可以简单地编写:

let dataResult = await dynamoDB.get(params).promise();