Rumah  >  Artikel  >  hujung hadapan web  >  setTimeout - senapang kaki tamat masa maksimum

setTimeout - senapang kaki tamat masa maksimum

Linda Hamilton
Linda Hamiltonasal
2024-11-23 16:48:21749semak imbas

setTimeout - max timeout footgun

Baru-baru ini saya menemui senapang kaki dalam kehidupan sebenar, yang berkaitan dengan setTimeout, saya terpaksa menjalankan tamat masa untuk katakan 28 hari untuk pemasa jualan, saya mempunyai cap waktu UTC untuk penghujungnya hari, jadi dengan pendekatan naif, saya melakukan ini

 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);

Saya terkejut, ini tidak berfungsi atau berfungsi dengan baik, kerana kod dalam setTimeout dilaksanakan tanpa menunggu tamat masa, saya memutuskan untuk nyahpepijat dalam penyemak imbas, dan saya melihat bahawa kawalan melompat ke dalam panggilan balik setTimeout hampir serta-merta.

Apa masalah di sini?

Melihat halaman MDN setTimeout, https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#maximum_delay_value , adalah jelas bahawa terdapat had maksimum sehingga setTimeout() akan dijalankan dengan tepat, khususnya
2,147,483,647ms atau (24.8 hari) atau (2**31 - 1) ms, ini kerana penyemak imbas menyimpan kelewatan sebagai integer bertanda 32-bit secara dalaman.

Jadi apabila anda melepasi tamat masa lebih daripada 24.8 hari, terdapat limpahan integer dan kod dilaksanakan serta-merta atau lebih tepat dengan tempoh tamat masa yang lebih rendah daripada yang dijangkakan. Itu mengecewakan, dan tiada ralat !!!

Penyelesaian yang mungkin untuk masalah ini

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);

Atas ialah kandungan terperinci setTimeout - senapang kaki tamat masa maksimum. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn