Topik temu duga representatif

Bagaimanakah anda menggunakan scheduler.postTask dengan selamat bersama sandaran progresif?

FrontendSukar
Pasukan Editorial Offer.ccDiterbitkan Dikemas kini

Soalan

Satu aplikasi web mesti memproses indeks carian, pemaparan yang boleh dilihat dan pramuat turun berkeutamaan rendah pada benang utama. Reka bentuk penjadual dengan scheduler.postTask dan terangkan tentang keutamaan, pembatalan, scheduler.yield, pelayar yang tidak disokong, serta cara membuktikan interaksi kekal responsif.

1. Soalan

Satu halaman mengemas kini hasil carian semasa pengguna menaip sambil menghuraikan indeks luar talian dan mempramuat turun halaman seterusnya. Reka bentuk lapisan tugas menggunakan API Penjadualan Tugas Berkeutamaan (Prioritized Task Scheduling API): kemas kini yang boleh dilihat harus berjalan dengan segera tanpa pramuat turun latar belakang menyekat input. Terangkan scheduler.postTask(), scheduler.yield(), isyarat pembatalan, dan tingkah laku apabila API tersebut tidak tersedia.

2. Kekangan dan penjelasan

  • Semua tugas berjalan dalam satu gelung peristiwa tetingkap atau Worker; fungsi segerak yang panjang masih menyekat benang tersebut.
  • Kelaskan kerja kepada sekurang-kurangnya keutamaan user-blocking, user-visible, dan background.
  • Penatalan, perubahan laluan, atau input baharu boleh menjadikan kerja usang, jadi ia mesti boleh dibatalkan atau boleh diubah keutamaannya.
  • Sediakan sandaran yang berfungsi; ketepatan perniagaan tidak boleh bergantung pada sokongan pelayar.

3. Pendekatan teras

scheduler.postTask(callback, options) meletakkan panggilan balik ke dalam baris gilir dengan keutamaan dan mengembalikan Promise. priority boleh terdiri daripada user-blocking, user-visible, atau background. Hantarkan AbortSignal untuk membatalkan; TaskController yang dikongsi juga boleh mengubah keutamaan tugas yang belum bermula. scheduler.yield() membolehkan fungsi tak segerak mengembalikan kawalan secara sukarela kepada pelayar sebelum meneruskan.

Keutamaan mengubah susunan; ia tidak mendahului (preempt) JavaScript yang sedang berjalan. Pastikan setiap panggilan balik sentiasa pendek dan beralih (yield) antara ketulan kerja. Apabila API tidak tersedia, gunakan kelompok kecil setTimeout atau MessageChannel, atau penjadual rangka kerja sedia ada, sambil mengekalkan semantik pembatalan dan hasil usang yang sama.

4. Pelaksanaan rujukan

javascript
const scheduler = globalThis.scheduler;

function scheduleWork(task, priority, signal) {
  if (scheduler?.postTask) {
    return scheduler.postTask(task, { priority, signal });
  }

  return new Promise((resolve, reject) => {
    const run = () => {
      if (signal?.aborted) {
        reject(signal.reason);
        return;
      }
      Promise.resolve().then(task).then(resolve, reject);
    };
    setTimeout(run, priority === "background" ? 50 : 0);
  });
}

async function indexInChunks(items, signal) {
  for (let i = 0; i < items.length; i += 100) {
    await scheduleWork(() => buildIndex(items.slice(i, i + 100)),
      "background", signal);
    if (scheduler?.yield && i + 100 < items.length) {
      await scheduler.yield({ signal });
    }
  }
}

5. Prestasi dan ketepatan

Keutamaan tidak mengubah hasil program atau mengganggu panggilan balik yang sedang berjalan; ia hanya mempengaruhi susunan relatif tugas yang belum bermula. Promise daripada scheduler.postTask() diselesaikan dengan nilai pulangan panggilan balik, manakala ralat panggilan balik atau pembatalan harus dikendalikan sebagai penolakan oleh pemanggil.

Sempadan prestasi sebenar ialah tempoh tugas dan jumlah keseluruhan kerja: gelung segerak selama 200 ms masih menyekat input apabila diletakkan dalam baris gilir berkeutamaan rendah. Ukur Tugas Panjang (Long Tasks), kelewatan input, dan kadar kejayaan pembatalan bagi setiap kelompok, kemudian laras saiz ketulan kerja. Kerja berat CPU yang boleh berjalan secara selari mungkin lebih sesuai berada dalam Worker; keutamaan semata-mata tidak dapat menyembunyikan kebuluran benang utama.

6. Tindakan susulan dan perangkap

  • Kesan globalThis.scheduler?.postTask dan bukannya meneka sokongan daripada jenama atau versi pelayar.
  • Sesuatu AbortSignal membatalkan kerja yang belum bermula atau yang memerhatikan isyarat tersebut; ia tidak boleh menghentikan secara paksa panggilan balik segerak yang sudah berjalan.
  • Keutamaan dinamik bukanlah pemintasan (preemption). Jika sesuatu tugas telah keluar dari baris gilir, gunakan semakan versi peringkat perniagaan untuk mengelakkan daripada melakukan perubahan dengan hasil yang usang.
  • Sandaran setTimeout tidak dapat menghasilkan semula semua semantik keutamaan asli, jadi sahkan kerja yang kelihatan, kerja latar belakang, dan laluan pembatalan secara eksplisit.

7. Bacaan lanjut

Bandingkan scheduler.postTask() dengan requestIdleCallback(), MessageChannel, dan penjadual rangka kerja: yang pertama menyediakan keutamaan dan pembatalan yang eksplisit, panggilan balik melahu bergantung pada peluang melahu, saluran mesej hanya membariskan kerja, dan rangka kerja mungkin menambah semantik kitaran hayat komponen. Pilih berdasarkan keserasian, jenis tugas, dan tingkah laku yang diukur.

8. Mata pemarkahan temu duga

Boleh menerangkan sempadan keutamaan

Calon harus merangkumi tiga keutamaan tersebut, Promise yang dikembalikan, dan hakikat bahawa hanya tugas yang belum bermula disusun; ia bukan pemintasan benang.

Boleh mereka bentuk kerja yang boleh dibatalkan

Mereka harus menggunakan AbortSignal atau TaskController, menerangkan bahawa panggilan balik yang telah dimulakan tidak boleh dihentikan secara paksa, dan menambah semakan versi hasil usang.

Boleh menulis sandaran progresif

Mereka harus mengesan ciri terlebih dahulu, kemudian menyediakan penjadualan pemasa, saluran mesej, atau rangka kerja sambil mengekalkan kelas tugas dan tingkah laku pembatalan.

Boleh membuktikan faedah dengan data

Mereka harus mengukur Tugas Panjang, kelewatan input, tempoh ketulan, dan kadar kejayaan pembatalan, serta menyedari bahawa Worker mengasingkan kerja yang benar-benar berat bagi CPU.

Sumber awam

Soalan berkaitan