Лямбда-функция не вызывает функцию Https.request, когда данные извлекаются из DynamoDB с использованием Async / Await - PullRequest
0 голосов
/ 30 апреля 2019

В 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 Ответ

1 голос
/ 30 апреля 2019

Есть несколько возможных проблем, но наиболее поразительным для меня является тот факт, что вы неправильно смешиваете стили программирования.

Вы объявили обработчик как асинхронную функцию, что нормально. Но внутри асинхронной функции вы смешиваете ожидаемый вызов с классическим вызовом функции в стиле продолжения, которого вы не ожидаете должным образом.

Что происходит, так это то, что ваша Lambda выполняет первую часть (вызов динамо), а затем среда выполнения завершает выполнение до фактического завершения вашего второго вызова функции в стиле продолжения.

Одним из решений является завершение вашего запроса https в обещании и ожидание этого в теле обработчика 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();
    });
}

Кстати - вам не нужно обещать для работы с DynamoDB с использованием async / await. Клиент DynamoDB имеет встроенную поддержку обещаний, которые вы можете ожидать. Просто позвоните по номеру .promise() и дождитесь этого. Например, вы можете просто написать:

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