用Lambda查询DynamoDB不做任何事情



Lambda函数的代码如下:

console.log('Loading function');
var aws = require('aws-sdk');
var ddb = new aws.DynamoDB();
function getUser(userid) {
    var q = ddb.getItem({
        TableName: "Users",
        Key: {
            userID: { S: userid } }
        }, function(err, data) {
            if (err) {
                console.log(err);
                return err;
            }
            else {
                console.log(data);
            }
    });
    console.log(q);
}

exports.handler = function(event, context) {
    console.log('Received event');
    getUser('user1');
    console.log("called DynamoDB");
    context.succeed();
};

我有一个[Users]表,定义如下:

{
    "cognitoID": { "S": "token" },
    "email": { "S": "user1@domain.com" },
    "password": { "S": "somepassword" },
    "tos_aggreement": { "BOOL": true },
    "userID": { "S": "user1" }
}

当我调用函数(从AWS控制台或CLI)时,我可以在日志中看到消息,但getItem()的回调从未被调用。

我尝试做getItem(params)没有回调,然后定义回调完成,成功和失败,但当我做send()时,甚至完整的回调也没有被调用。

我知道调用是异步的,我想也许,lambda函数在查询完成之前就完成了,因此回调不会被调用,但是,我在函数末尾添加了一个简单的愚蠢循环,调用在3秒后超时,没有调用回调。

我尝试了不同的函数batchGetItem, getItem, listTables和scan。结果是一样的,没有错误,但是回调函数永远不会被调用。

我打赌,如果我不使用Lambda查询dynamoDB,它会得到我的结果,所以我真的很想知道为什么这里什么都没有发生。

我为该函数创建了一个角色,并创建了一个策略,该策略允许访问dynamoDB中我需要但无效的功能。

策略如下:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction"
            ],
            "Resource": "arn:aws:lambda:*:*:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:GetItem",
                "dynamodb:BatchGetItem",
                "dynamodb:Scan",
                "dynamodb:PutItem",
                "dynamodb:Query",
                "dynamodb:GetRecords",
                "dynamodb:ListTables"
            ],
            "Resource": "arn:aws:dynamodb:*:*:*"
        },
        {
            "Action": [
                "logs:*"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}

我在模拟器中运行了这个策略,它像我想象的那样工作。建议吗?

所以,结果证明代码是正确的。问题是dynamodb API使用所有这些回调,基本上函数在数据被检索之前结束。

最快的修复方法是删除context.succeed()调用,然后将检索数据。当然,使用异步模块会有所帮助,如果你不想使用它,只需添加一个计数器或布尔值到你的回调,然后等待,直到值发生变化,表明回调已被调用(这有点糟糕,如果你想到它)

我有一些类似的问题,没有找到很多有用的资源。这是我最后做的。也许有更聪明的人能告诉我们这是不是最好的。

function getHighScores(callback) {
    var params = {
        TableName : 'sessions',
        ScanFilter: {"score":{"AttributeValueList":[{"N":"0"}], "ComparisonOperator":"GT"}},
    };
    var dynamo = new AWS.DynamoDB();
    dynamo.scan(params, function(err, data) {
        if (err) {
            console.log (err)
            callback(err);
        } else {
            callback(data.Items);
            console.log(data.Items);
        }
    });
} 

getHighScores(function (data) {
    console.log(data);
    context.succeed(data);
});

总之,通过主函数将回调回传给较小的函数,允许应用程序继续直到完成Dynamo。保持上下文。

我的问题是我的lambda在VPC中运行,以便连接到ElastiCache。这将导致对公共Internet资源(如DynamoDB和API Gateway)的任何查询无限期挂起。为了访问DynamoDB,我必须在VPC内设置NAT网关。

我的问题是我试图调用的函数接受一个回调

因此,Node.js只是继续执行Lambda函数,一旦它到达结束,它告诉Lambda关闭,因为它已经完成了。 下面是如何使用Promises: 解决这个问题的例子
'use strict';
exports.handler = async (event, context) => {
  // WRAP THE FUNCTION WHICH USES A CALLBACK IN A PROMISE AND RESOLVE IT, WHEN
  // THE CALLBACK FINISHES
  return await new Promise( (resolve, reject) => {
    // FUNCTION THAT USES A CALLBACK
    functionThatUsesACallback(params, (error, data) => {
      if(error) reject(error)
      if(data) resolve(data)
    });
  });
};

现在,由于node.js引入了async/await,这可以使它在主函数终止之前等待查询调用返回:

let result = await ddb.getItem(params).promise();
return result;

要避免回调地狱,请使用Promises。youtube上有一个叫funfunfunction的人做的一些非常好的教程

相关内容

  • 没有找到相关文章

最新更新