AWS Lambda调用DynamoDB getItem无回调响应问题排查
问题根源与修复方案
这是Lambda环境下常见的异步执行问题——Node.js 8.10的Lambda会在同步代码执行完毕后立刻终止进程,完全不会等待异步回调函数执行。你的ddb.getItem是异步操作,当Lambda运行到console.log("Completed call")后,就认为函数执行完成了,直接结束进程,导致回调里的代码根本没机会运行,这就是为什么你看不到回调里的日志。
下面给两种靠谱的修复方式,推荐第一种,代码更清晰易维护:
方式一:用Async/Await + Promise(推荐)
AWS SDK的所有异步方法都可以通过.promise()转换成Promise,配合async/await就能让Lambda等待异步操作完成,代码逻辑也更线性:
const AWS = require('aws-sdk'); AWS.config.update({region: 'eu-west-1'}); const ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'}); // 把readData改成async函数 async function readData(){ console.log("In the readData() function"); const params = { TableName: "desks", Key: { "desk_id": {N:'1'} } }; console.log("Set params"); try { // 用await等待getItem完成,不用嵌套回调 const data = await ddb.getItem(params).promise(); console.log("Success", data.Item); return data.Item; // 可以把结果返回给Lambda的入口函数 } catch (err) { console.log("Error", err); throw err; // 抛出错误让Lambda捕获并上报 } } // Lambda的入口函数也要用async,确保等待readData执行完 exports.handler = async (event) => { await readData(); return { statusCode: 200, body: JSON.stringify("数据读取成功") }; };
方式二:用Lambda的回调机制(兼容传统回调写法)
如果你更习惯回调风格,可以让readData接收Lambda的callback参数,在getItem的回调里调用它,明确告诉Lambda“等我这个异步操作完再结束”:
const AWS = require('aws-sdk'); AWS.config.update({region: 'eu-west-1'}); const ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'}); function readData(callback){ console.log("In the readData() function"); const params = { TableName: "desks", Key: { "desk_id": {N:'1'} } }; console.log("Set params"); ddb.getItem(params, function(err, data) { console.log("In getItem callback function"); if (err) { console.log("Error", err); callback(err); // 把错误传给Lambda,终止执行并上报错误 } else { console.log("Success", data.Item); callback(null, data.Item); // 把结果传给Lambda,结束执行 } }); console.log("Completed call"); } // Lambda入口函数,把callback传给readData exports.handler = (event, context, callback) => { readData(callback); };
额外要确认的点
虽然你说权限没问题,但还是可以快速排查下:
- 确认Lambda的IAM角色确实包含
dynamodb:GetItem权限(或者AmazonDynamoDBFullAccess策略) - 检查
desks表确实在eu-west-1区域,且存在desk_id为1的项(注意你用的是数字类型{N:'1'},如果表中desk_id是字符串,要改成{S:'1'})
内容的提问来源于stack exchange,提问作者David Fulton
相关产品推荐
相关产品推荐

