Lambda查询DynamoDB返回非数组导致前端JS forEach报错问题咨询
问题解决方案
核心原因
报错forEach is not a function是因为前端拿到的响应结果不是数组,通常有两个触发场景:
- Lambda返回时未指定
Content-Type头,API Gateway将返回值识别为普通文本而非JSON,或存在跨域拦截导致返回结构异常 - API Gateway未开启Lambda代理集成,直接将Lambda的完整返回对象(包含
statusCode/body等字段)返回给前端,而非返回body内的用户数组
修复步骤
1. 后端Lambda代码调整
添加必要的响应头,同时兼容DynamoDB Scan分页场景(Scan单次最多返回1MB数据),修改后代码如下:
import json import boto3 from boto3.dynamodb.conditions import Key, Attr def lambda_handler(event, context): client = boto3.resource('dynamodb') table = client.Table('HelloWorldDatabase') response = table.scan( FilterExpression=Attr('ID').gt('0') ) items = response['Items'] # 分页拉取全部数据,小数据量可删除该部分逻辑 while 'LastEvaluatedKey' in response: response = table.scan( FilterExpression=Attr('ID').gt('0'), ExclusiveStartKey=response['LastEvaluatedKey'] ) items.extend(response['Items']) return { 'statusCode': 200, 'headers': { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' # 允许跨域,可替换为Amplify实际域名限制访问 }, 'body': json.dumps(items) }
修改完Lambda后,在API Gateway对应资源下重新部署API生效。
2. 前端代码兼容调整
如果不修改API Gateway的集成配置,可以直接调整前端代码兼容返回结构,修改后代码如下:
document.getElementById('getPosts').addEventListener('click', getPosts); function getPosts(){ fetch('<你的API Gateway调用地址>') .then((res) => res.json()) .then((data) => { // 自动判断返回结构:如果是数组直接用,否则取body字段解析 const userList = Array.isArray(data) ? data : JSON.parse(data.body); let output = '<h2 class="mb-4">DynamoDB</h2>'; userList.forEach(function(post){ console.log(post); output += ` <div class="card card-body mb-3"> <h3>${post.ID}</h3> <p>${post.Name}</p> <p>${post.LatestGreetingTime}</p> <p>${post.website}</p> </div> `; }); document.getElementById('output').innerHTML = output; }) .catch(err => console.error('请求异常:', err)); }
验证方法
直接在浏览器访问API Gateway调用地址,若返回内容以[开头即为符合要求的数组结构;若返回内容以{开头且包含statusCode/body字段,只需确认开启API Gateway的Lambda代理集成即可。
内容的提问来源于stack exchange,提问作者Alan John Heslop
相关产品推荐
相关产品推荐

