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

JavaScript try块抛出异常后catch块未立即执行问题求助

问题原因

  • Node.js 的 EventEmitter 事件机制不会等待异步回调执行完成。你在 parser 中给 data 事件绑定了 async 回调,但 parseFile 触发 data 事件时,只会执行回调逻辑,不会等待回调返回的 Promise 变更状态,就会继续触发下一行的 data 事件。3行数据的 rowCb 回调几乎是同时启动的,启动后第一时间就把共享变量 recordsProcessed 自增到了3,三个 processRow 同时进入异步等待状态。
  • 异步回调的闭包捕获的是 recordsProcessed 变量的引用,而非触发回调时的瞬时值。等三个 processRow 先后抛出异常进入 catch 块时,共享的 recordsProcessed 已经被修改为3,所以所有报错都会打印 Failure at record 3。

修复方案

方案1:串行逐行处理(完全符合预期执行顺序)

如果要求严格按文件行顺序处理,前一行处理完成后再处理下一行,需要改造 parser 函数,先收集所有行再串行消费:

async parser(fileBuffer: Buffer, rowCb: (row: Record<string, any>) => Promise<void>, ...) : Promise<number> {
  return new Promise((resolve, reject) => {
    const rows: Record<string, any>[] = []
    parseFile(fileBuffer, options)
      .on('error', (error:any) => reject(error))
      .on('data', row => rows.push(row))
      .on('end', async (count: any) => {
        // 串行逐行执行回调
        for (const row of rows) {
          try {
            await rowCb(row)
          } catch (e) {
            return reject(e)
          }
        }
        resolve(count)
      })
  })
}

方案2:保留并行处理,修复行号打印问题

如果允许并行处理行数据,只需要修复行号打印错误的问题,不用修改 parser,只需要在回调内部存储当前行号的局部副本即可:

let recordsProcessed = 0
await parser(fileBuffer,
  async (row: Record<string, any>) => {
    recordsProcessed += 1
    // 存储当前行号的局部副本,不会被后续自增修改
    const currentRecordNo = recordsProcessed
    try {
      console.log('Processing record', currentRecordNo)
      await processRow(row)
    } catch (e) {
      console.log('Failure at record', currentRecordNo)
    }
  }
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 23:24:01