最近我在现实生活中发现了一把枪,它与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中文网其他相关文章!