javascript: 暂停 setTimeout();

IT技术 javascript timeout
2021-01-30 01:22:10

如果我有一个通过设置的活动超时运行var t = setTimeout("dosomething()", 5000)

无论如何要暂停和恢复它?


有没有办法获得当前超时的剩余时间?
或者我必须在一个变量中,当设置超时时,存储当前时间,然后我们暂停,得到现在和那时之间的差异?

6个回答

你可以这样包装window.setTimeout,我认为这类似于你在问题中的建议:

var Timer = function(callback, delay) {
    var timerId, start, remaining = delay;

    this.pause = function() {
        window.clearTimeout(timerId);
        remaining -= Date.now() - start;
    };

    this.resume = function() {
        start = Date.now();
        window.clearTimeout(timerId);
        timerId = window.setTimeout(callback, remaining);
    };

    this.resume();
};

var timer = new Timer(function() {
    alert("Done!");
}, 1000);

timer.pause();
// Do some stuff...
timer.resume();
@Josh979:你真的不需要这样做,这样做是个坏主意,因为它暴露了应该是内部的变量。也许您已将代码粘贴到一个块中(例如在一个 中if (blah) { ... })或其他什么东西?
2021-03-12 01:22:10
如果你这样做,timer.resume(); timer.resume();你最终会同时有两个超时。这就是为什么你会想要在简历的一开始就clearTimeout(timerId)先做或if (timerId) return;短路。
2021-03-18 01:22:10
嘿,我喜欢这个答案,但我不得不拉:var timerId, start, remaining;在 Class 范围之外并在remaining = delay;里面添加以捕获参数。像魅力一样工作!
2021-03-22 01:22:10
@yckart:回滚,抱歉。这是一个很好的补充,除了setTimeout()在 Internet Explorer <= 9中添加附加参数不起作用。
2021-04-02 01:22:10
出于某种原因,这在初始化后只对我运行一次。
2021-04-08 01:22:10

像这样的事情应该可以解决问题。

function Timer(fn, countdown) {
    var ident, complete = false;

    function _time_diff(date1, date2) {
        return date2 ? date2 - date1 : new Date().getTime() - date1;
    }

    function cancel() {
        clearTimeout(ident);
    }

    function pause() {
        clearTimeout(ident);
        total_time_run = _time_diff(start_time);
        complete = total_time_run >= countdown;
    }

    function resume() {
        ident = complete ? -1 : setTimeout(fn, countdown - total_time_run);
    }

    var start_time = new Date().getTime();
    ident = setTimeout(fn, countdown);

    return { cancel: cancel, pause: pause, resume: resume };
}
最好的,爸爸!
2021-03-13 01:22:10
我换+new Date()new Date().getTime(),因为它是速度快:jsperf.com/date-vs-gettime
2021-03-20 01:22:10

不。您需要取消它 ( clearTimeout),测量自启动以来的时间并使用新时间重新启动它。

Tim Downs答案的稍微修改版本但是,由于蒂姆回滚了我的编辑,我必须自己回答这个问题。我的解决方案可以使用 extraarguments作为第三个 (3, 4, 5 ...) 参数并清除计时器:

function Timer(callback, delay) {
    var args = arguments,
        self = this,
        timer, start;

    this.clear = function () {
        clearTimeout(timer);
    };

    this.pause = function () {
        this.clear();
        delay -= new Date() - start;
    };

    this.resume = function () {
        start = new Date();
        timer = setTimeout(function () {
            callback.apply(self, Array.prototype.slice.call(args, 2, args.length));
        }, delay);
    };

    this.resume();
}

正如 Tim 提到的,额外的参数在 中不可用IE lt 9,但是我做了一些工作,以便它也可以在 中使用oldIE

用法: new Timer(Function, Number, arg1, arg2, arg3...)

function callback(foo, bar) {
    console.log(foo); // "foo"
    console.log(bar); // "bar"
}

var timer = new Timer(callback, 1000, "foo", "bar");

timer.pause();
document.onclick = timer.resume;

“暂停”和“继续”在 的上下文中没有多大意义setTimeout,这是一次性的事情。您可能想要暂停一系列链接setTimeout调用,在这种情况下,不要安排下一个调用(可能通过 取消未完成的调用,clearTimeout如下所示)。setTimeout它本身不会循环,没有什么可以暂停和恢复的。

如果你的意思是setInterval不,你不能暂停它,你只能取消它 ( clearInterval) 然后重新安排它。规范计时器部分中所有这些的详细信息

// Setting
var t = setInterval(doSomething, 1000);

// Pausing (which is really stopping)
clearInterval(t);
t = 0;

// Resuming (which is really just setting again)
t = setInterval(doSomething, 1000);