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

VS Code接收大量日志时短暂无响应/崩溃的代码修复咨询

解决VS Code日志大量输出时无响应/崩溃的问题

原代码的核心问题在于高频触发VS Code日志输出API,以及全局变量引发的潜在数据混乱,导致主线程被阻塞。以下是修复后的代码:

class TestGetLog {
    // 改用类静态属性存储未完成的日志片段,避免全局污染
    private static recordEndData = '';
    // 节流定时器ID,用于批量输出日志
    private static logTimer: NodeJS.Timeout | null = null;
    // 批量日志缓存
    private static logBuffer: string[] = [];

    static createActiveDatalog(logger: LogOutputChannel, context: ExtensionContext): void {
        const connect = createConnection({ host: '127.0.0.1', port: 20001 }, () => {
            logger.show();
            const sendPorts = [20001, 20003];
            if (connect.localPort && sendPorts.includes(connect.localPort)) {
                connect.destroy();
                // 用setTimeout避免递归调用导致栈溢出
                setTimeout(() => TestGetLog.createActiveDatalog(logger, context), 100);
                return;
            }
        });

        connect.on('data', (data) => {
            const logData = TestGetLog.recordEndData + String(data);
            const lines = logData.split('\n');
            
            if (logData.endsWith('\n')) {
                TestGetLog.recordEndData = '';
                // 将完整行加入缓存
                TestGetLog.logBuffer.push(...lines.slice(0, lines.length - 1));
            } else {
                TestGetLog.recordEndData = lines[lines.length - 1];
                // 将完整行加入缓存
                TestGetLog.logBuffer.push(...lines.slice(0, lines.length - 1));
            }

            // 启动节流定时器,每隔200ms批量输出一次日志
            TestGetLog.flushLogs(logger);
        });

        connect.on('close', () => {
            // 连接关闭时清空剩余缓存
            if (TestGetLog.logBuffer.length > 0) {
                logger.info(TestGetLog.logBuffer.join('\n'));
                TestGetLog.logBuffer = [];
            }
            // 输出剩余的未完成片段
            if (TestGetLog.recordEndData) {
                logger.info(TestGetLog.recordEndData);
                TestGetLog.recordEndData = '';
            }
            if (TestGetLog.logTimer) {
                clearTimeout(TestGetLog.logTimer);
                TestGetLog.logTimer = null;
            }
        });

        // 处理连接错误,避免未捕获异常
        connect.on('error', (err) => {
            logger.error(`日志连接出错: ${err.message}`);
            connect.destroy();
        });

        // 将连接实例存入上下文,防止被GC回收
        context.subscriptions.push({
            dispose: () => {
                connect.destroy();
                if (TestGetLog.logTimer) clearTimeout(TestGetLog.logTimer);
            }
        });
    }

    private static flushLogs(logger: LogOutputChannel): void {
        if (TestGetLog.logTimer) return;
        
        TestGetLog.logTimer = setTimeout(() => {
            if (TestGetLog.logBuffer.length === 0) {
                TestGetLog.logTimer = null;
                return;
            }
            // 批量输出缓存的日志
            logger.info(TestGetLog.logBuffer.join('\n'));
            TestGetLog.logBuffer = [];
            TestGetLog.logTimer = null;
        }, 200); // 可根据需求调整间隔时间
    }
}

关键修改点说明

  • 移除全局变量:将recordEndData改为类的静态私有属性,避免多次调用方法时的数据交叉污染。
  • 批量日志输出:增加日志缓存和节流定时器,将高频的logger.info调用合并为批量调用,减少VS Code主线程的UI更新压力,避免卡顿。
  • 修复拼写错误:修正post→port、reocrdEndData→recordEndData的拼写问题。
  • 优化连接逻辑:用setTimeout代替直接递归调用createActiveDatalog,避免栈溢出风险。
  • 完善资源清理:在连接关闭、插件销毁时清空缓存、关闭定时器、销毁连接,防止内存泄漏。
  • 添加错误处理:捕获连接错误并输出日志,避免未处理异常导致插件崩溃。

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

相关产品推荐
方舟 Agent Plan

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

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