Cara bermain Batal Pesan
- Baca instruksi level dan daftar kejadian di atas garis waktu, mis. pembeli memesan di 0 ms lalu menekan Batal di 500 ms. Di bawah editor tertulis fungsi yang dipanggil game di tiap kejadian.
- Tulis kode halamannya di editor.
fetch,setTimeout, danAbortSignal.timeoutmemakai jam virtual, jadi masakan 5 detik langsung selesai tapi waktunya tercatat persis. tampilkan(nilai)mengubah layar pembeli. Layarmu dan layar target tampil berdampingan, lengkap dengan waktu tiap perubahan.- Garis waktu diperbarui setiap kamu mengetik. Bar hijau berarti pesanan sampai, bar abu dengan tanda × berarti dibatalkan di titik itu, dan garis putus-putus hijau adalah target.
- Tekan Cek jawaban atau Ctrl + Enter. Yang dicek adalah kapan tiap request berhenti, timer yang kamu pasang, dan isi layar, bukan teks kodemu.
- Kalau buntu, buka Petunjuk. Petunjuk pertama mengarahkan, petunjuk terakhir hampir menjawab.
- Level yang sudah selesai tetap tercentang saat kamu kembali dengan browser yang sama.
Yang kamu pelajari
- Level 1
AbortController dan signal
new AbortController()memberisignaluntukfetch. Memanggilcontroller.abort()menghentikan request yang memegang signal itu. - Level 2
AbortError dan err.name
Request yang dibatalkan ditolak dengan
DOMExceptionbernamaAbortError. Bedakan dari koneksi putus (TypeError) lewaterr.name. - Level 3
Batas waktu dengan setTimeout
Timer yang memanggil
controller.abort()setelah sekian milidetik, lalu dihapus denganclearTimeoutdifinallybegitu request selesai. - Level 4
AbortSignal.timeout
Signal yang batal sendiri setelah
msmilidetik, tanpa controller dan timer. AlasannyaTimeoutError, bukanAbortError. - Level 5
Membatalkan pencarian lama
Setiap pencarian baru membatalkan controller pencarian sebelumnya, supaya hasil yang datang terlambat tidak menimpa hasil terbaru.
- Level 6
Satu signal untuk banyak request
Semua
fetchyang menerima signal yang sama berhenti bersama saatabort()dipanggil sekali. - Level 7
Listener abort
signal.addEventListener("abort", ...)membuat pekerjaan selainfetch, sepertisetTimeout, ikut berhenti. - Level 8
signal.aborted
Cek
signal.abortedsetelah langkah yang tidak bisa dibatalkan, sebelum hasilnya dipakai. - Level 9
AbortSignal.any
Menggabungkan beberapa signal, mis. tombol Batal dan batas waktu, jadi satu signal yang batal begitu salah satunya batal.
Membatalkan request tidak sama dengan mengabaikan hasilnya
Ada dua cara agar hasil pencarian lama tidak tampil: abaikan saja hasilnya saat datang, atau batalkan request-nya. Keduanya menjaga layar tetap benar, tapi hanya pembatalan yang menghentikan pekerjaannya. Tanpa abort(), browser tetap menunggu dan mengunduh balasan yang tidak dipakai, dan di game ini dapur tetap memasak sampai bar request-nya penuh.
Sebaliknya, abort() hanya menghentikan yang memegang signal itu. Pekerjaan yang tidak menerima signal, seperti muatFoto di level 8, tetap jalan sampai selesai. Untuk langkah seperti itu, cek signal.aborted sebelum memakai hasilnya. Pakai signal milik pencarian itu sendiri, karena variabel controller di luar fungsi sudah diganti pencarian yang lebih baru.
Tanya jawab
Apakah harus daftar akun untuk bermain?
Tidak. Semua level bisa dimainkan tanpa akun. Kemajuanmu disimpan di browser yang kamu pakai, jadi akan hilang kalau data browser dihapus.
Kenapa request yang dibatalkan masuk ke catch?
fetch mengembalikan Promise, dan abort() membuat Promise itu ditolak dengan AbortError. Kalau tidak ditangkap, browser menulis Uncaught (in promise) AbortError di console. Tangkap dengan try/catch, lalu cek err.name supaya pembatalan yang disengaja tidak tampil sebagai pesan gagal.
Apa beda AbortError dan TimeoutError?
controller.abort() tanpa argumen menolak dengan AbortError. AbortSignal.timeout(ms) menolak dengan TimeoutError, jadi kamu bisa membedakan pembeli yang membatalkan dari dapur yang kelamaan. Kalau kamu memanggil controller.abort(alasan), fetch ditolak dengan alasan itu apa adanya.
Apakah controller bisa dipakai lagi setelah abort?
Tidak. Signal yang sudah batal tetap batal, dan fetch baru dengan signal itu langsung ditolak tanpa mengirim request. Buat new AbortController() untuk setiap pesanan atau pencarian baru, seperti di level 5.
Bagaimana memakai AbortController di React?
Buat controller di dalam useEffect, berikan signalnya ke fetch, lalu panggil controller.abort() di fungsi cleanup. Cleanup jalan saat komponen dilepas atau dependensinya berubah, jadi request lama berhenti persis seperti pencarian di level 5.
Apakah kodeku benar-benar mengirim request?
Tidak. fetch di game ini tiruan yang berjalan di Web Worker sandbox, dengan jam virtual. Waktu masak 5 detik selesai seketika, dan hasilnya selalu sama setiap dijalankan.