使用负数延迟调用setTimeout是否可行?

69
下面的代码片段设置了一个超时时间,我希望至少等待一秒钟:
var currentTimeMillis = new Date().getTime();
// do stuff...
var sleepTime = 1000 - (new Date().getTime() - currentTimeMillis);

考虑到 sleepTime 可能是负数,像这样调用 setTimeout 是安全的吗:

setTimeout(callback, sleepTime)

我需要在调用setTimeout之前检查负值吗?

5个回答

78
根据MDN参考资料,规范要求有最小的延迟时间。
如果提供的时间比这个时间短(HTML5规范为4ms),浏览器将忽略您的延迟并使用最小值。
因此,负数应该没问题,因为它会小于最小值。
显然,这并非总是如此(这不是Web开发的常态吗!)。根据 (http://programming.aiham.net/tag/browser-compatibility/) :

提供setTimeout一个负数的时间不一定会导致回调函数被调用。在其他浏览器中可以工作,但在Internet Explorer(8或更低版本)中,您必须确保任何负时间都被更改为零。

我自己没有测试过这点,但像Thomasz所说,最好还是保险起见。

39
搞定IE8,您无需担心超时! - Michael Cole
1
在 https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/ 使用其中一个虚拟机测试 IE 8 后,我可以确认如果你传递一个负的超时时间给 setTimeout,IE 8 的实现确实不会执行你的函数。至少现在 IE 8 已经太古老了,大多数人可以安全地忽略它。 - Mark Amery

73

宁愿安全也不要抱有侥幸心理:

setTimeout(callback, Math.max(sleepTime, 0))

哦,太酷了,出于某种原因,我以为我必须这样做 if (sleepTime > 0) setTimeout (...) else,但那会有点丑。 - ripper234
2
如果性能是一个问题,总是可以使用 setTimeout(callback, sleepTime>0?sleepTime:0) - unsynchronized
1
这是一个很好的解决方案。其他东西的问题在于它让代码看起来比实际复杂。 - boy

2
您也可以使用条件语句,如下所示:
if (sleepTime < 0) {
  sleepTime = 0;
}
setTimeout(callback, sleepTime);

或者使用三元语句 setTimeout(callback, sleepTime > 0 ? sleepTime : 0) - Oliver Chalk
这是正好在此回答上面的答案。 - Yash Kumar Verma

0

嗯...提到的解决方案解决了在调用setTimeout时出现的问题,因此每次调用都需要编写。直接在setTimeout中解决不是更好吗?

// Run this once.
(function(){
    var oldSetTimeout = setTimeout
    setTimeout = function(callback, delay){
        return oldSetTimeout(callback, Math.max(delay, 0))
    }
})()

// Call setTimeout safely with a negative delay.
setTimeout(function(){ console.log("Hello World") }, -42)

-1

没问题,可以使用负数毫秒作为超时时间。

        setTimeout(() => {
        btn.style.top = '16.2%';
        btn.style.left = '35.8%';
        btn.style.transition = 'all 1.2s ease';
        },-1.2*1000);

这段代码会在延迟1.2*1000秒后,基于id为“btn”的按钮触发transition,并使用style topstyle left

2
负超时时间与0超时时间相同。指定-1.2 * 1000最多只会混淆问题。 - Remember Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接