>웹 프론트엔드 >JS 튜토리얼 >setTimeout - 최대 시간 초과 풋건

setTimeout - 최대 시간 초과 풋건

Linda Hamilton
Linda Hamilton원래의
2024-11-23 16:48:21844검색

setTimeout - max timeout footgun

최근에 실생활에서 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 - 최대 시간 초과 풋건의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.