最近我在現實生活中發現了一把槍,它與setTimeout有關,我必須為銷售計時器運行一個28天的超時,我有一個UTC時間戳作為結束那天,所以用天真的方法,我做到了
const date1 = new Date(timestamp1); // Difference in milliseconds const timeout = date2.getTime() - Date.now(); setTimeout(()=>{ // some code to turn off some flags / remove some banner },timeout);
令我驚訝的是,這並沒有起作用或效果太好,因為setTimeout中的程式碼沒有等待超時就執行了,我決定在瀏覽器中調試,我看到控制幾乎立即跳到setTimeout回調中。
查看setTimeout的MDN頁面,https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#maximum_delay_value,很明顯setTimeout()運行有一個最大限制準確地,具體地
2,147,483,647ms 或(24.8 天)或(2**31 - 1)ms,這是因為瀏覽器在內部將延遲儲存為 32 位元有符號整數。
因此,每當您傳入超過 24.8 天的超時時,就會出現整數溢出,程式碼會立即執行,或者超時持續時間比預期短。太糟糕了,而且沒有錯! ! !
const days = 30; const timeout = days * 24 * 60 * 60 * 1000; console.log('timeto', timeout); setTimeout(function () { console.log('ticked immediately'); // --> executed almost instantly }, timeout); class LongTimeout { constructor(cb, timeout) { this.timeStart = document.timeline ? document.timeline.currentTime : performance.now(); this.lastAnimationFrame = this.runTimer(cb, timeout); } runTimer(cb, timeout) { if(this.cancelled) return; const currTimeStamp = performance.now(); const elapsed = currTimeStamp - this.timeStart; if (elapsed >= timeout) { cb(); window.cancelAnimationFrame(this.lastAnimationFrame); } else { console.log('tick', elapsed, timeout); this.lastAnimationFrame = requestAnimationFrame(() => this.runTimer(cb, timeout) ); } } cancelTimeout() { window.cancelAnimationFrame(this.lastAnimationFrame); this.cancelled = true; this.lastAnimationFrame = null; } } const longTimer = new LongTimeout(() => { console.log(`Tick after ${timeout}`); // timeout works -> does not execute immediately }, timeout);
以上是setTimeout - 最大超時 footgun的詳細內容。更多資訊請關注PHP中文網其他相關文章!