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

如何解决异步函数脚本中console.group()分组混乱的问题?

如何解决异步函数脚本中console.group()分组混乱的问题?

这个问题我太懂了!异步操作打断console分组的情况真的超级影响调试体验,尤其是多个实例并行执行的时候,日志完全乱成一锅粥😅。

问题根源

你遇到的核心问题是JavaScript的事件循环机制:当await this.asyncMethod()执行时,当前函数会暂停,把控制权交还给事件循环,这时候第二个new C('green')的同步代码会立刻执行,它的console.groupCollapsed和run日志就会插在第一个实例的异步操作中间,等第一个实例的setTimeout完成后,它的asyncMethod日志才会输出,最终导致分组完全混乱。

下面给你两个实用的解决方案,你可以根据需求选择:


方案一:让实例按顺序执行(实时输出日志)

如果你可以接受两个实例的代码按顺序执行(先执行完红色实例的所有操作,再执行绿色实例),可以用一个全局Promise队列来控制执行顺序,这样每个实例的console分组就不会被打断:

// 全局执行队列,确保实例按顺序执行
let executionQueue = Promise.resolve();

class C {
    color;
    colorName;

    constructor(color) {
        this.color = `font-weight: strong; color: ${color}`;
        this.colorName = color;
        // 将当前实例的run方法加入队列,等待前一个实例完成后再执行
        executionQueue = executionQueue.then(() => this.run());
    }

    async run() {
        console.groupCollapsed('%c Class C ', this.color, this.colorName);
        console.log('%c run', this.color);
        await this.asyncMethod();
        this.syncMethod();
        console.groupEnd();
    }

    async asyncMethod() {
        return new Promise((resolve) => {
            setTimeout(() => {
                console.log('%c asyncMethod', this.color, this.colorName);
                resolve();
            }, 99);
        });
    }

    syncMethod() {
        console.group('%c syncMethod', this.color, this.colorName);
        this.subSyncMethod();
        console.groupEnd();
    }

    subSyncMethod() {
        console.log('%c subSyncMethod', this.color, this.colorName);
    }
}

new C('red');
new C('green');

这个方案的原理是让每个实例的run方法等待队列前的所有操作完成后再执行,这样日志会严格按照实例顺序输出,分组完全整齐,和你想要的预期结果一致。


方案二:日志队列延迟输出(实例并行执行)

如果你需要两个实例并行执行,但又想保持分组完整,可以给每个实例添加一个日志队列,先把所有console操作存起来,等实例的所有异步操作完成后,再一次性输出所有日志:

class C {
    color;
    colorName;
    // 私有日志队列,存储当前实例的所有console操作
    #logQueue = [];

    constructor(color) {
        this.color = `font-weight: strong; color: ${color}`;
        this.colorName = color;
        // 执行逻辑,完成后刷新日志
        this.run().then(() => this.#flushLogs());
    }

    async run() {
        this.#logQueue.push(['groupCollapsed', '%c Class C ', this.color, this.colorName]);
        this.#logQueue.push(['log', '%c run', this.color]);
        await this.asyncMethod();
        this.syncMethod();
        this.#logQueue.push(['groupEnd']);
    }

    async asyncMethod() {
        return new Promise((resolve) => {
            setTimeout(() => {
                this.#logQueue.push(['log', '%c asyncMethod', this.color, this.colorName]);
                resolve();
            }, 99);
        });
    }

    syncMethod() {
        this.#logQueue.push(['group', '%c syncMethod', this.color, this.colorName]);
        this.subSyncMethod();
        this.#logQueue.push(['groupEnd']);
    }

    subSyncMethod() {
        this.#logQueue.push(['log', '%c subSyncMethod', this.color, this.colorName]);
    }

    // 一次性执行所有日志操作
    #flushLogs() {
        this.#logQueue.forEach(([method, ...args]) => {
            console[method](...args);
        });
    }
}

new C('red');
new C('green');

这个方案的好处是两个实例的代码会并行执行,不会互相阻塞,但日志会等到每个实例的所有异步操作完成后才输出,这样每个实例的分组都是完整的,不会被其他实例的日志打断。


备注:内容来源于stack exchange,提问作者iiic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 17:33:15