【问题标题】:Lambda function is not calling Https.request function, when data is retrieved from DynamoDB using Async / Await当使用 Async / Await 从 DynamoDB 检索数据时,Lambda 函数未调用 Https.request 函数
【发布时间】:2019-09-19 02:24:51
【问题描述】:

在 AWS-Lambda 中,我正在调用以从 DynamoDB 表中检索数据并使用该数据向 API Gateway 发出发布请求。 我使用 Async / await 从 DynamoDB 检索数据。但是,在向 API Gateway 发出发布请求时,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();
}

【问题讨论】:

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


    【解决方案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();
        });
    }
    

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

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

    【讨论】:

      猜你喜欢
      • 2020-01-31
      • 2020-08-13
      • 2022-01-27
      • 2017-12-17
      • 2019-02-17
      • 2021-08-06
      相关资源
      最近更新 更多