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

Node.js+Express环境下createReadStream抛出错误无法被catch处理

问题排查与解决方案

核心问题原因

  • Promise 仅能捕获构造函数执行过程中同步抛出的错误,你在entry事件的回调函数里抛出的错误属于异步回调中的异常,不属于Promise构造函数的同步执行上下文,所以不会被Promise的catch捕获,会直接抛出到全局导致进程终止。
  • Stream的事件回调里抛出的错误,不会自动触发Stream本身的error事件,也不会向上传递到你之前监听的ReadStream的error事件,所以你之前写的error监听也捕获不到这里的异常。

修复方案

修复逻辑:给每一段Stream都添加error监听,所有异步回调内的业务逻辑包try/catch,捕获到异常后主动调用Promise的reject方法传递错误,不要直接throw。
修改后的functions.js代码参考:

const fs = require('fs')
const unzip = require('unzip') // 补充缺失的依赖引入

module.exports = {
    test: function (request, response, fichier){
        return new Promise((resolve, reject) => {
            let readStream
            try {
                readStream = fs.createReadStream(fichier)
                .on('error', function(err){
                    console.log("read stream error")
                    reject(err)
                })
                .on('close', function(){
                    console.log("read stream end")
                    resolve("ok")
                })
                .pipe(unzip.Parse())
                .on('error', function(err) {
                    // 捕获unzip流的所有错误
                    console.log("unzip stream error")
                    // 销毁上游读流避免内存泄漏
                    readStream.destroy()
                    reject(err)
                })
                .on('entry', function (entry) {
                    try {
                        // 业务逻辑写在try块内
                        // throw("uh") 你的测试错误
                        entry.autodrain() // 必须处理entry,否则流会卡住无法触发结束事件
                    } catch (e) {
                        // 主动捕获业务异常并传递给Promise
                        console.log("entry handle error")
                        readStream.destroy()
                        reject(e)
                    }
                });
            } catch (e) {
                // 捕获创建流过程中同步抛出的错误
                reject(e)
            }
            console.log("end end")
        })
    }
}

额外注意事项

  • 所有流式操作的每一段链路都必须单独添加error监听,任何一段流报错没有监听都会直接抛到全局终止进程。
  • 处理unzip的entry事件时,每个entry都必须做消费、丢弃等处理,否则流会暂停卡住,永远不会触发close事件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 19:18:01