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

ERR_NETWORK_IO_SUSPENDED导致无限请求问题排查

问题分析

你的同步逻辑通过while(this.active)循环持续调用SomeClass.sync(),正常运行时能按需同步数据,但遇到以下场景会出问题:

  • 浏览器标签页长时间非活跃或电脑休眠时,浏览器会暂停JS异步任务执行,同时挂起网络请求;
  • 标签页恢复后,之前处于pending状态的SomeClass.sync()会批量触发,加上while循环无间隔的特性,短时间内产生数千次请求,导致页面卡顿;
  • net::ERR_NETWORK_IO_SUSPENDED是浏览器底层的网络挂起错误,部分场景下不会触发Promise的reject,因此无法被外层catch块捕获。
解决方案

1. 给同步请求添加最小间隔

在每次同步完成后增加固定的最小延迟,避免无间隔连续发起请求,即使标签页恢复后,也能有效控制请求频率:

static async sync(): Promise<void> {
    while (this.active) {
        try {
            await SomeClass.sync();
            // 添加1秒最小间隔,可根据业务需求调整时长
            await new Promise(resolve => setTimeout(resolve, 1000));
        } catch (error) {
            console.error(error);
            this.active = false;
        }
    }
}

2. 监听标签页可见性,暂停/恢复同步

利用Page Visibility API,在标签页不可见时暂停循环,可见时再恢复,从根源避免休眠期间积累pending请求:

static async sync(): Promise<void> {
    const handleVisibilityChange = () => {
        // 标签页不可见时,暂存活跃状态并暂停同步
        if (document.hidden) {
            this._prevActive = this.active;
            this.active = false;
        } else {
            // 标签页恢复可见时,恢复活跃状态并重启同步
            if (this._prevActive) {
                this.active = true;
                this.sync();
            }
        }
    };

    // 绑定可见性变化监听
    document.addEventListener('visibilitychange', handleVisibilityChange);

    while (this.active) {
        try {
            await SomeClass.sync();
        } catch (error) {
            console.error(error);
            this.active = false;
        }
    }

    // 循环结束后移除监听(可根据业务场景选择是否保留)
    document.removeEventListener('visibilitychange', handleVisibilityChange);
}

// 类内新增临时变量,用于保存标签页休眠前的活跃状态
private static _prevActive = false;

3. 结合网络状态检测

通过navigator.onLine事件监听系统网络状态,网络断开时暂停同步,恢复时再继续:

static async sync(): Promise<void> {
    const handleNetworkChange = () => {
        if (!navigator.onLine) {
            this._prevActive = this.active;
            this.active = false;
        } else {
            if (this._prevActive) {
                this.active = true;
                this.sync();
            }
        }
    };

    // 绑定网络状态变化监听
    window.addEventListener('online', handleNetworkChange);
    window.addEventListener('offline', handleNetworkChange);

    while (this.active) {
        try {
            await SomeClass.sync();
        } catch (error) {
            console.error(error);
            this.active = false;
        }
    }

    // 循环结束后移除监听
    window.removeEventListener('online', handleNetworkChange);
    window.removeEventListener('offline', handleNetworkChange);
}

private static _prevActive = false;

4. 在SomeClass.sync()内部处理网络挂起

如果SomeClass.sync()基于fetch或XMLHttpRequest,可以手动处理网络挂起场景:

  • 对于fetch,使用AbortController在标签页不可见时主动中止请求,避免pending状态积累:
// 修改SomeClass.sync()方法
static async sync(): Promise<void> {
    const controller = new AbortController();
    const signal = controller.signal;

    // 监听标签页可见性,不可见时中止请求
    const abortOnHidden = () => {
        if (document.hidden) controller.abort();
    };
    document.addEventListener('visibilitychange', abortOnHidden);

    try {
        const response = await fetch('/your-sync-api', { signal });
        // 处理同步响应逻辑
    } catch (error) {
        if (error.name === 'AbortError') {
            // 捕获主动中止的错误,无需向外抛出
            return;
        }
        throw error;
    } finally {
        document.removeEventListener('visibilitychange', abortOnHidden);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 13:53:10