javascript 使用 Lambda 查询 DynamoDB 没有任何作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30739965/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Querying DynamoDB with Lambda does nothing
提问by E.T
I have the following code for a Lambda function:
我有以下 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();
};
I have a [Users] table that is defined as such:
我有一个 [Users] 表,定义如下:
{
"cognitoID": { "S": "token" },
"email": { "S": "[email protected]" },
"password": { "S": "somepassword" },
"tos_aggreement": { "BOOL": true },
"userID": { "S": "user1" }
}
When I call the function (from the AWS Console or the CLI) I can see the messages in the logs but the callback for the getItem() is never called.
当我调用函数(从 AWS 控制台或 CLI)时,我可以看到日志中的消息,但从未调用 getItem() 的回调。
I tried with doing getItem(params) with no callback, then defined the callbacks for complete, success and failure but when I do the send(), even the complete callback isn't called either.
我尝试在没有回调的情况下执行 getItem(params),然后为完成、成功和失败定义了回调,但是当我执行 send() 时,甚至没有调用完整的回调。
I know that the calls are asynchronous and I thought that maybe, the lambda function was finishing before the query was done and therefore the callback would not be called, but, I added a simple stupid loop at the end of the function and the call timed out after 3 seconds, without the callbacks being called at all.
我知道调用是异步的,我想也许 lambda 函数在查询完成之前就完成了,因此不会调用回调,但是,我在函数的末尾添加了一个简单的愚蠢循环,并且调用计时3 秒后退出,根本没有调用回调。
I tried with different functions batchGetItem, getItem, listTables and scan. Result is the same, no error but the callback function is never called.
我尝试了不同的功能 batchGetItem、getItem、listTables 和 scan。结果是一样的,没有错误,但回调函数永远不会被调用。
I'm betting that if I query dynamoDB without using Lambda it will get me the results so I'm really wondering why nothing is happening here.
我敢打赌,如果我在不使用 Lambda 的情况下查询 dynamoDB,它会给我结果,所以我真的很想知道为什么这里什么也没发生。
I create a role for the function and I created a policy that would allow access to the functionalities in dynamoDB that I need but to no avail.
我为该函数创建了一个角色,并创建了一个策略,该策略允许访问我需要但无济于事的 dynamoDB 中的功能。
The policy looks like this:
该政策如下所示:
{ "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": "*" } ] }
{ "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": "*" } ] }
I ran the policy in the simulator and it worked as I thought it would. Suggestions?
我在模拟器中运行了策略,它按我的想法工作。建议?
回答by E.T
So, it turns out that the code is correct. The problem is that the dynamodb API uses all those callbacks and basically the function ends BEFORE the data has been retrieved.
所以,事实证明代码是正确的。问题是 dynamodb API 使用所有这些回调,并且基本上函数在检索数据之前结束。
The quickest fix is to remove the context.succeed()
call and the data will be retrieved.
Of course using the async module would help and if you don't want to use that, just add a counter or a boolean to your callback and then wait until the value has changed, indicating that the callback has been called (which kind of sucks if you think of it)
最快的解决方法是删除context.succeed()
调用并检索数据。当然,使用 async 模块会有所帮助,如果您不想使用它,只需在回调中添加一个计数器或布尔值,然后等待值发生变化,表明回调已被调用(这很糟糕)如果你想到了)
回答by Derek Maxson
I had some similar issues and did not find many helpful resources. Here's what I ended up doing. Probably someone smarter can tell us if this is bestest.
我遇到了一些类似的问题,但没有找到很多有用的资源。这就是我最终要做的。也许更聪明的人可以告诉我们这是否是最好的。
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);
});
In summary, having the passback of callback through the main function to the smaller function, allows the application to continue until completing the Dynamo. Keep the context.succeed in the secondary function or continue other function there.
总之,通过主函数将回调回传到较小的函数,允许应用程序继续运行,直到完成 Dynamo。在辅助功能中保持 context.succeed 或在那里继续其他功能。
回答by Justin Chapweske
My problem is that my lambda was running in a VPC in order to connect to ElastiCache. This causes any queries to public Internet resources such as DynamoDB and API Gateway to hang indefinitely. I had to set up a NAT Gateway within my VPC in order to access DynamoDB.
我的问题是我的 lambda 在 VPC 中运行以连接到 ElastiCache。这会导致对公共 Internet 资源(例如 DynamoDB 和 API Gateway)的任何查询无限期挂起。我必须在我的 VPC 中设置一个 NAT 网关才能访问 DynamoDB。
回答by Neil Yue
Now since node.js has introduced async/await, this can make it wait until the query call returns before the main function terminates:
现在,由于 node.js 引入了 async/await,这可以让它在主函数终止之前等待查询调用返回:
let result = await ddb.getItem(params).promise();
return result;
回答by Attaque
My problem was that the function I was trying to call accepted a callback.
我的问题是我试图调用的函数接受了回调。
Node.js therefore just continued the execution of the Lambda function and once it reaches the end it tells Lambda to shut down because it's done.
因此,Node.js 只是继续执行 Lambda 函数,一旦执行完毕,它就会告诉 Lambda 关闭,因为它已经完成。
Here's an example of how you can solve it using Promises:
这是一个如何使用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)
});
});
};
回答by yks
To avoid callback hell, use Promises. There are some pretty good tutorials on youtube by guy called funfunfunction.
为了避免回调地狱,请使用 Promises。youtube 上有一些非常好的教程,由一个叫做 funfunfunction 的人提供。