delay 参数将转换为带符号的32位整数,这有效地将延迟限制为 2147483647 ms
(约 24.8 天)
2147483647 === Math.pow(2, 31) - 1 === parseInt('01111111111111111111111111111111', 2)
在nodejs和浏览器中执行的情况有所差异
Nodejs 中
setInterval(callback, delay[, ...args])
setTimeout(callback, delay[, ...args])
When
delay
is larger than2147483647
or less than1
, thedelay
will be set to1
. Non-integer delays are truncated to an integer.
行为统一!当 delay 大于 2147483647
时,将会被设置为 1。-- Here
// 下述 delay 都为 1
setInterval(() => {
console.log(+new Date())
}, 3333333000)
setInterval(() => {
console.log(+new Date())
}, 9999999000)
setInterval(() => {
console.log(+new Date())
}, 2147483647 + 1)
浏览器
- Let timeout be the second argument to the method, or zero if the argument was omitted.
- Apply the ToString() abstract operation to timeout, and let timeout be the result. [ECMA262]
- Apply the ToNumber() abstract operation to timeout, and let timeout be the result. [ECMA262]
- If timeout is an Infinity value, a Not-a-Number (NaN) value, or negative, let timeout be zero.
- Round timeout down to the nearest integer, and let timeout be the result.
- Return timeout.
关注第四点:如果超时是Infinity值,非数字(NaN)值或负值,则将超时设置为零。– Here
通过测试规律发现,浏览器中超过32位的,会自动截取32位,如果第32为1,即负数,则将超设置为0;否则会将后32位,转化为相应毫秒值进行执行!
parseInt('0000000000000000000101110111000', 2) === 3000
上述为 3000 ms
示例1:将第32位变为1
setTimeout(() => {
console.log(+new Date())
}, parseInt('1000000000000000000101110111000', 2)) // 立即执行
示例1:将第32保持0,增加第33位为1,让数字溢出
setTimeout(() => {
console.log(+new Date())
}, parseInt('10000000000000000000101110111000', 2)) // 3000ms后执行
其他: 现代浏览器中,setTimeout()/setInterval()
- Timeouts throttled to ≥ 4ms
- Timeouts in inactive tabs throttled to ≥ 1000ms
参考地址
- https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout
- https://nodejs.org/api/timers.html#timers_settimeout_callback_delay_args
- https://www.w3.org/TR/2011/WD-html5-20110525/timers.html