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

如何处理异步函数mpv.getProperty抛出的未捕获错误?

MPV异步函数未捕获Socket错误的处理方案

问题背景

这个问题并非讨论Promise拒绝的重复问题,我无法修改mpv.getProperty的行为,请求重新开放问题。

我在使用异步函数mpv.getProperty时遇到了一个问题:该函数有时会触发未捕获的错误,而非返回Promise拒绝,导致常规的.catch和try-catch都无法捕获,服务器直接崩溃。

我尝试过用try-catch包裹调用,也写了包装函数,但都无效,代码如下:

app.get('/filename', (req, res) => {
    async function getFilenameProperty() {
        try {
            return await mpv.getProperty("filename")
        } catch (error) {
            console.log(error)
        }
    }

    getFilenameProperty().then((f) => {
        res.status(200).send(f)
    }).catch((error) => {
        console.log(error)
        res.status(400).send(`Error getting filename`)
    })
})

复现步骤

  1. 创建Express服务器,导入node-mpv库
  2. 初始化实例:
const mpv = new mpvAPI({"verbose": true}, ["--fullscreen"])
const app = express()
  1. 配置上述/filename端点,发送GET请求后服务器直接崩溃

错误信息

node:events:495
      throw er; // Unhandled 'error' event
      ^

Error [ERR_SOCKET_CLOSED]: Socket is closed
    at new NodeError (node:internal/errors:405:5)
    at Socket._writeGeneric (node:net:953:8)
    at Socket._write (node:net:975:8)
    at writeOrBuffer (node:internal/streams/writable:392:12)
    at _write (node:internal/streams/writable:333:10)
    at Writable.write (node:internal/streams/writable:337:10)
    at /hot/GitHub/remotetv-fullstack-project/back/node_modules/node-mpv/lib/ipcInterface/ipcInterface.js:209:17
    at new Promise (<anonymous>)
    at ipcInterface.send (/hot/GitHub/remotetv-fullstack-project/back/node_modules/node-mpv/lib/ipcInterface/ipcInterface.js:190:10)
    at ipcInterface.getProperty (/hot/GitHub/remotetv-fullstack-project/back/node_modules/node-mpv/lib/ipcInterface/ipcInterface.js:117:15)
Emitted 'error' event on Socket instance at:
    at emitErrorNT (node:internal/streams/destroy:151:8)
    at emitErrorCloseNT (node:internal/streams/destroy:116:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  code: 'ERR_SOCKET_CLOSED'
}

为什么原来的代码无效?

从错误栈可以看出,这个错误是Socket实例触发的未捕获error事件,既不是mpv.getProperty返回的Promise拒绝,也不是同步抛出的错误。

在Node.js中,所有EventEmitter实例如果触发了error事件但没有绑定对应的监听器,就会直接抛出错误并终止进程。这种异步事件触发的错误不在当前函数调用栈里,所以try-catch和Promise的.catch都无法捕获。

解决方案

1. 监听底层Socket的error事件

找到mpv实例底层的Socket对象,给它绑定error监听器,就能直接捕获这类错误:

// 初始化mpv后立即绑定
const mpv = new mpvAPI({"verbose": true}, ["--fullscreen"]);
// 访问mpv的IPC接口对应的Socket(根据node-mpv的内部结构)
if (mpv.ipcInterface?.socket) {
    mpv.ipcInterface.socket.on('error', (err) => {
        console.log('MPV Socket错误捕获:', err);
        // 可以在这里处理连接异常,比如标记连接状态、尝试重连等
    });
}

2. 监听mpv实例的自定义错误事件

查看node-mpv文档,部分库会在底层出错时暴露自定义错误事件,可以直接监听mpv实例的error事件:

mpv.on('error', (err) => {
    console.log('MPV实例错误:', err);
});

3. 全局异常监听(临时应急方案)

如果找不到具体的事件源,可以临时给进程绑定全局监听,但不推荐作为长期方案,因为会掩盖其他未知错误:

process.on('uncaughtException', (err) => {
    console.log('未捕获全局异常:', err);
    // 根据错误码判断是否是Socket关闭错误
    if (err.code === 'ERR_SOCKET_CLOSED') {
        // 针对性处理,比如重启mpv连接
    }
});

优化后的端点代码

结合Socket错误监听,调整后的端点代码可以避免服务器崩溃:

// 初始化并绑定错误监听
const mpv = new mpvAPI({"verbose": true}, ["--fullscreen"]);
if (mpv.ipcInterface?.socket) {
    mpv.ipcInterface.socket.on('error', (err) => {
        console.log('MPV Socket错误:', err);
    });
}

// 简化后的端点处理
app.get('/filename', async (req, res) => {
    try {
        const filename = await mpv.getProperty("filename");
        res.status(200).send(filename);
    } catch (err) {
        console.log('获取文件名失败:', err);
        res.status(400).send('获取文件名失败');
    }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 15:02:05