You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Promise链式调用S3操作时出现“Cannot read property 'push' of undefined”错误

解决AWS Lambda Node.js 12下S3操作间歇性"Cannot read property 'push' of undefined"错误

我之前也碰到过类似的棘手问题,结合你的代码和报错信息,这个问题大概率是循环变量作用域冲突+异步操作上下文混乱导致的,下面是具体的分析和修复方案:

核心问题定位

你的报错来自AWS SDK内部的event_listeners.js,提示dataListeners数组未定义——这通常是因为异步请求的上下文被意外覆盖了。看你的代码,循环里用了var record:var是函数级作用域,在async循环中,所有迭代会共享同一个record变量。当await暂停当前迭代时,下一次迭代会修改record的值,导致之前未完成的S3请求绑定到了错误的上下文,最终触发SDK内部的数组未初始化错误。

另外,你代码里多层嵌套的await写法(比如Body: (await generateHTML( (await s3.getObject(...).promise()).Body.toString('utf-8'), ...)))也会加重上下文混乱的概率,让异步操作的执行逻辑变得不可预期。

修复步骤

1. 替换循环变量为const(最关键)

把for (var record of event.Records)改成for (const record of event.Records)。const是块级作用域,每个迭代都会创建独立的record变量,彻底避免异步操作中变量被覆盖的问题。

2. 拆分深层嵌套的await

将多层嵌套的异步操作拆分为单独的步骤,既能提升代码可读性,也能避免上下文冲突:

exports.handler = async (event) => {
  for (const record of event.Records) {
    // 快速过滤不需要处理的对象
    if (!record.s3.object.key.includes(".") || record.s3.object.key === "website/") {
      continue;
    }

    try {
      // 1. 获取源S3对象的原始HTML内容
      const sourceObject = await s3.getObject({
        Bucket: record.s3.bucket.name,
        Key: record.s3.object.key
      }).promise();
      const rawHtml = sourceObject.Body.toString('utf-8');

      // 2. 调用HTML处理函数
      const processedHtml = await generateHTML(rawHtml, record.s3.bucket.name);

      // 3. 上传处理后的HTML到目标桶
      await s3.putObject({
        Body: processedHtml,
        Bucket: DestBucket,
        Key: record.s3.object.key.slice("website/".length),
        ACL: 'public-read',
        ContentType: 'text/html'
      }).promise();
    } catch (error) {
      // 添加错误日志,方便定位特定失败的对象
      console.error(`处理对象 ${record.s3.object.key} 失败:`, error);
      // 可以根据业务需求选择抛出错误终止,或者继续处理其他对象
      throw error;
    }
  }
  return { statusCode: 200, body: "所有对象处理完成" };
};

3. 额外检查项

  • 确认generateHTML的异步实现:确保这个函数始终返回有效的Promise,不会在某些场景下返回undefined或者抛出未捕获的错误——这类问题也可能间接导致SDK的上下文异常。
  • AWS SDK版本兼容性:Node.js 12环境中Lambda自带的AWS SDK版本和Node.js 10的有差异,如果依赖特定SDK特性,可以在package.json中显式指定SDK版本(比如"aws-sdk": "^2.1000.0"),然后打包部署。

为什么Node.js 10下能正常运行?

Node.js 10对async/await的处理逻辑和Node.js 12有细微差异,加上之前的回调模式下,闭包抵消了var的作用域问题,所以这个错误没有暴露出来。切换到纯async/await模式后,var的作用域缺陷就被放大了。

内容的提问来源于stack exchange,提问作者HOK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 10:22:48