67

The following snippet sets a timeout that I'd like to last at least a second:

var currentTimeMillis = new Date().getTime();
// do stuff...
var sleepTime = 1000 - (new Date().getTime() - currentTimeMillis);

Given that sleepTime can be a negative number, is it safe to call setTimeout, like this:

setTimeout(callback, sleepTime)

Or do I need to check for negative values before calling setTimeout?

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
ripper234
  • 222,824
  • 274
  • 634
  • 905

5 Answers5

76

According to the MDN reference, the specification requires that there is a minimum timeout.

If you provide something less than this (HTML5 spec says 4ms) then the browser will just ignore your delay and use the minimum.

So negatives should be fine, since it'll just be less than the minimum.


Apparently, this isn't always the case (isn't that always the way with web development!). According to ( http://programming.aiham.net/tag/browser-compatibility/ ):

Providing setTimeout a negative time will not always result in the callback function being called. This works in other browsers, but in Internet Explorer (8 or lower) you have to make sure any negative times are changed to zero.

I haven't tested this myself, but like Thomasz said, it's probably better to be safe.

Jonathon Bolster
  • 15,811
  • 3
  • 43
  • 46
  • 39
    Screw IE8. No timeout for u! – Michael Cole Oct 29 '15 at 02:18
  • 1
    After testing on IE 8 using one of the VMs from https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/, I can confirm that IE 8's `setTimeout` implementation does indeed never execute your function if you pass it a negative timeout. At least IE 8 is ancient enough now that *most* of us can safely ignore it. – Mark Amery Jan 10 '20 at 16:35
71

Better be safe than sorry:

setTimeout(callback, Math.max(sleepTime, 0))
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • Ah cool, for some reason I thought I must do `if (sleepTime > 0) setTimeout(...) else`, which would have been a bit uglier. – ripper234 Dec 08 '11 at 12:51
  • 2
    there's always `setTimeout(callback,sleepTime>0?sleepTime:0)`, if performance is an issue – unsynchronized Dec 29 '18 at 02:01
  • 1
    This is a great solution. The problem with the other stuff is it makes the code look more complex than it is. – boy May 13 '22 at 14:01
2

You could also use a conditional statement, like so:

if (sleepTime < 0) {
  sleepTime = 0;
}
setTimeout(callback, sleepTime);
Malekai
  • 4,765
  • 5
  • 25
  • 60
dku.rajkumar
  • 18,414
  • 7
  • 41
  • 58
0

Hmm... The solutions mentioned solves the problem at the call to setTimeout, so it needs to be written each time a call is made. Isn't it better to solve it directly in 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)
Alex Wiese
  • 8,142
  • 6
  • 42
  • 71
Peppe L-G
  • 7,351
  • 2
  • 25
  • 50
-1

Yes it is ok to use negative timeout in milli-seconds like this.

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

This code will initiate transition on button of id btn after 1.2*1000 seconds of delay,style top and style left

Zia Khan
  • 188
  • 2
  • 9