时光穿梭停止术,如何完全停止setTimeout的递归

176 阅读1分钟

如何在用setTimeout 来实现setInterval中来彻底结束setTimeout的循环

image.png

由于 intervalId 在每次 setTimeout 调用后都会被更新,因此 return () => clearTimeout(intervalId); 返回的函数实际上只能清除最后一次的 setTimeout 调用,而不是整个循环。这意味着,一旦循环开始,通过这个函数来停止整个循环是不可行的,因为它只能影响到最后一次的定时器。

    let running = true; // 引入一个标志变量来控制循环的运行状态

    function loop() {
        if (!running) {
            return; // 如果running为false,则不继续执行循环体
        }

        intervalId = setTimeout(() => {
            fn(); // 执行传入的函数

            if (running) {
                loop(); // 如果running仍然为true,则继续递归调用loop
            }
        }, time);
    }

    loop(); // 启动定时器

    // 返回一个函数,用于停止循环
    return function stop() {
        running = false; // 将running设置为false,以停止后续的递归调用
        if (intervalId !== null) {
            clearTimeout(intervalId); // 清除当前正在等待的定时器(如果有的话)
            intervalId = null; // 重置intervalId为null,表示没有正在等待的定时器
        }
    };
}

如何使用它去停止循环呢?

image.png

这样我们就解决了setTimeout难以结束递归的问题了。