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