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

Node.js脚本中s3.putObject未执行直接抛错的问题排查

问题产生原因

核心是Node.js的异步非阻塞I/O与事件循环机制导致的执行顺序不符合直觉:

  • s3.putObject 属于异步网络I/O操作,调用该方法时不会同步阻塞等待S3上传流程执行完成,仅仅是把上传任务和对应的回调函数注册到事件队列,就会立刻继续执行当前调用栈内的后续代码。
  • 你在if分支里的实际执行顺序是:
    1. 执行s3.putObject(params, callback),仅注册异步上传任务,未真正启动/完成上传逻辑
    2. 立刻同步执行下一行的throw new Error('There were errors'),该错误直接在fs.readFile的回调调用栈中抛出,直接终止整个Node.js进程
    3. 进程退出后,事件队列里等待调度的S3上传任务根本没有执行机会,自然不会触发实际上传动作。
  • 注释掉手动抛错的代码后,当前fs.readFile回调的同步代码会全部执行完、调用栈清空,事件循环才会调度队列里的S3上传任务执行,因此文件可以正常上传。
逻辑验证方法

你可以在代码对应位置加两行日志就能直观看到执行顺序:

if (numberOfErrors > 0) { 
    s3.putObject(params, (err) => {
        console.log('S3上传回调被触发') // 进程提前终止,该行永远不会打印
        if (err) { throw err; }
        console.log("File uploaded to S3 " + bucket)                                     
    })
    console.log('即将抛出错误终止进程') // 该行会先于所有异步回调打印
    throw new Error('There were errors') 
}
额外注意事项

你当前代码里s3.putObject回调中写的if (err) { throw err; } 同样存在隐患:异步回调里抛出的错误不在原始调用栈中,外层的try/catch无法捕获,会直接触发未捕获异常导致进程崩溃。如果需要等上传完成后再判断是否抛出业务错误,建议将S3操作转为Promise写法,配合async/await控制执行顺序:

// 注意需要给fs.readFile的回调加上async关键字
fs.readFile(filePathName, async (err,data) => {
    // 省略前面的参数构造逻辑
    try {
        await s3.putObject(params).promise()
        console.log("File uploaded to S3 " + bucket)
        if (numberOfErrors > 0) {
            throw new Error('There were errors')
        }
        console.log('There were no errors')
    } catch(uploadErr) {
        // 统一处理上传错误、业务错误
        console.error('执行异常:', uploadErr)
    }
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 06:09:24