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

Set Interval ID事件调用时变更致并发轮询问题排查

问题分析与解决方案:定时器ID被覆盖导致多轮询并发问题

你碰到的这个问题太典型了——连续点击同一按钮时,旧的定时器ID被新创建的定时器ID覆盖,导致后续调用clearInterval时只能清除最新的那个定时器,之前的旧定时器就会在后台偷偷运行,最终出现多个轮询并发的情况。

核心问题拆解

举个例子:连续点击两次P1按钮,第一次点击生成的定时器ID存在this.interval1里,第二次点击时直接用新的ID覆盖了它,这时候旧定时器还在运行,但你手里已经没有它的ID了。之后点击P2时,clearInterval(this.interval1)只能清除第二次的定时器,第一次的那个就成了“孤儿”,继续在后台打印Polling 1.。

修复方案

解决思路很简单:每次启动新的轮询前,先清除当前进程自己的旧定时器,再清除其他进程的定时器,最后创建新的定时器。这样不管点击多少次同一按钮,旧的定时器都会被及时清理,不会遗留。

修改后的完整代码

class Handler {
    constructor () {
        this.interval1 = 0;
        this.interval2 = 0;
        this.interval3 = 0;
    }
    getToken(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    // 抽离清除其他定时器的逻辑,让代码更整洁
    clearOtherIntervals(current) {
        if (current !== 'one') clearInterval(this.interval1);
        if (current !== 'two') clearInterval(this.interval2);
    }
    process_one () {
        // 先清除自身旧定时器
        clearInterval(this.interval1);
        // 清除其他进程的定时器
        this.clearOtherIntervals('one');
        this.interval1 = setInterval(function() {
            console.log(" Polling 1. ")
        },300);
    }
    async process_two () {
        // 先清除自身旧定时器
        clearInterval(this.interval2);
        // 清除其他进程的定时器
        this.clearOtherIntervals('two');
        var scope_obj = this;
        this.interval2 = setInterval(async function() {
            console.log(" Polling 2. ");
            var data = await scope_obj.process_three();
        }, 500);
    }
    async process_three () {
        return axios( {
            url: "",
            data:{"data":"LOL"},
            headers : {
                'X-CSRFToken': this.getToken('csrftoken'),
                'Content-Type': 'application/x-www-form-urlencoded'
            }
        } )
    }
}
let event = new Handler();
$("#p1").click(function() {
    console.log("P1 started.")
    event.process_one ();
})
$("#p2").click(async function() {
    console.log("P2 started.")
    event.process_two ();
})
$("#p3").click(function() {
    console.log("P3 started.")
    event.process_three ();
})
<div class="row">
    <div class="col-lg-12">
        <button type="button" class="btn btn-warning" id="p1">P1</button>
        <button type="button" class="btn btn-warning" id="p2">P2</button>
        <button type="button" class="btn btn-warning" id="p3">P3</button>
    </div>
</div>

额外优化建议

  • 如果后续要增加更多进程,建议用一个对象来管理所有定时器ID,比如this.intervals = { one: 0, two: 0 },这样管理起来更灵活,也不容易出错。
  • 对于process_three,如果它不需要轮询,其实不需要给它分配interval变量,当前的逻辑是没问题的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:13:08