Node.js Async/Await中return语句返回结果异常问题排查
问题:DynamoDB查询返回空对象但日志能输出正确数据
我在写DynamoDB查询代码,同时学习Promise相关知识。console.log(resp.Items)能打印出预期的对象,说明查询格式没问题,但接口返回200状态码时却带空对象。查了资料改了好几次代码,还是没法返回resp.Items,猜可能函数在拿到数据前就返回了,但搞不懂为啥日志能正常输出。
相关代码
getTechs 函数
const AWS = require('aws-sdk') const dynamodb = new AWS.DynamoDB() const getTechs = async () => { try { const resp = await dynamodb .query({ ExpressionAttributeValues: { ':tech': { S: 'TECH#' }, }, KeyConditionExpression: 'PK = :tech', TableName: process.env.TABLE_NAME, ScanIndexForward: true, }) .promise() console.log(resp.Items) if (!resp.Items) { return { error: 'No Techs in the DB', } } return { tech: resp.Items, } } catch (error) { console.log('Error retrieving Tech List') console.log(error) return { error: 'Could not retrieve Tech List', } } }
Handler 函数
const { makeHandler } = require('./utils') const { getTechs } = require('../data') // const { Tech } = require('../entities') const inputSchema = { type: 'object', properties: { pathParameters: { type: 'object', properties: { tech: { type: 'string' }, }, required: ['tech'], }, }, required: ['pathParameters'], } const handler = async (event) => { const { techs, error } = await getTechs() const statusCode = error ? 500 : 200 const body = error ? JSON.stringify({ error }) : JSON.stringify({ techs }) return { statusCode, body, } } module.exports.handler = makeHandler({ handler })
executeTransactWrite 函数
const executeTransactWrite = async ({ tech, params }) => { const transactionRequest = tech.transactWriteItems(params) let cancellationReasons transactionRequest.on('extractError', (response) => { try { cancellationReasons = JSON.parse( response.httpResponse.body.toString() ).CancellationReasons } catch (err) { // suppress this just in case some types of errors aren't JSON parseable console.error('Error extracting cancellation error', err) } }) return new Promise((resolve, reject) => { transactionRequest.send((err, response) => { if (err) { err.cancellationReasons = cancellationReasons return reject(err) } return resolve(response) }) }) } module.exports = { executeTransactWrite, }
makeHandler 函数
const middy = require('middy') const { jsonBodyParser, validator, httpErrorHandler, } = require('middy/middlewares') const makeHandler = ({ handler, inputSchema }) => middy(handler) .use(jsonBodyParser()) .use(validator({ inputSchema })) .use(httpErrorHandler()) module.exports = { makeHandler }
问题原因及修复
核心问题是变量名不匹配:
getTechs函数返回的对象键是tech,但handler里解构时用的是techs,导致techs为undefined,经过JSON.stringify后就变成了空对象{}。
有两种修复方式:
- 修改
getTechs的返回值,把键名改成techs:
return { techs: resp.Items, }
- 修改handler中的解构和后续代码,匹配
getTechs返回的键名:
const { tech, error } = await getTechs() const body = error ? JSON.stringify({ error }) : JSON.stringify({ tech })
另外还有一个潜在问题:inputSchema要求请求必须携带pathParameters.tech字段,但getTechs函数完全没用到这个参数。如果接口是要根据路径参数查询特定技术项,那getTechs需要接收参数并修改DynamoDB的查询条件;如果不需要这个参数,就删掉inputSchema里的对应校验规则,否则请求会因为参数校验失败被拦截。
内容的提问来源于stack exchange,提问作者J Sig
相关产品推荐
相关产品推荐

