Jadwal adalah bagian dari layanan: pengingat dikirim setelah 30 detik, pesan status muncul setiap menit, dan pemeriksaan berkala berjalan di latar. Alat paling dasar untuk semuanya adalah timer — setTimeout dan setInterval — yang sudah kita singgung sejak chapter pertama section ini.
Timer sering diremehkan karena sintaksnya sederhana, padahal perilakunya menyimpan beberapa kontrak penting: id yang dikembalikannya, jeda minimal yang tidak persis seperti yang diminta, dan posisinya di antrean macrotask. Chapter ini merapikan semuanya dengan contoh yang diuji langsung.
setTimeout: Sekali Jalan Setelah Jeda #
setTimeout(callback, delay) mendaftarkan callback untuk dipanggil sekali, setelah sekurang-kurangnya delay milidetik. Kata sekurang-kurangnya penting: runtime menjanjikan callback tidak berjalan sebelum waktunya, tetapi tidak menjanjikan tepat pada waktunya — callback tetap harus mengantri di antrean macrotask dan menunggu call stack kosong, sesuai siklus event loop.
setTimeout mengembalikan id, nilai yang menjadi kunci pembatalan. Dengan clearTimeout(id), callback yang sudah terdaftar dapat dibatalkan sebelum pernah berjalan.
setInterval: Berulang Sampai Dihentikan #
setInterval(callback, delay) bekerja seperti setTimeout, tetapi mendaftarkan ulang callback secara berkala sampai dihentikan dengan clearInterval(id). Berkas contoh berikut memakai keempat fungsi timer sekaligus:
// pengatur-waktu.js
// setTimeout, clearTimeout, setInterval, dan clearInterval.
// --- 1. setTimeout + clearTimeout: pengingat yang dibatalkan ---
const idPengingat = setTimeout(() => {
console.log("pengingat: ambil kopi Budi");
}, 20);
setTimeout(() => {
clearTimeout(idPengingat);
console.log("pengingat dibatalkan sebelum sempat berjalan");
}, 10);
// --- 2. setInterval + clearInterval: pengadukan berulang ---
let hitungan = 0;
const idPengaduk = setInterval(() => {
hitungan += 1;
console.log(`pengadukan ke-${hitungan}`);
if (hitungan === 3) {
clearInterval(idPengaduk);
console.log("pengadukan selesai");
}
}, 10);Output yang Dihasilkan:
pengingat dibatalkan sebelum sempat berjalan
pengadukan ke-1
pengadukan ke-2
pengadukan ke-3
pengadukan selesaiMari kita telaah baris-baris pentingnya:
- Baris 5–7 (
setTimeoutpertama): pengingat didaftarkan untuk 20 milidetik, dan id-nya disimpan diidPengingatuntuk keperluan pembatalan. - Baris 9–12 (
setTimeoutkedua): timer ini berjalan lebih dulu karena jeda 10 milidetik. Ia memanggilclearTimeout(idPengingat), sehingga callback pengingat tidak pernah dieksekusi — keluaran tidak pernah menampilkan pesan pengingat. - Baris 16–23 (
setInterval): callback berulang setiap 10 milidetik;hitunganbertambah pada setiap giliran. - Baris 19–22 (kondisi berhenti): setelah hitungan mencapai 3,
clearInterval(idPengaduk)menghentikan pengulangan. Tanpa langkah ini, interval berjalan terus sampai program berakhir.
Delay 0 Tetap Menunggu Giliran #
Angka 0 pada delay sering dibaca sebagai “jalankan seketika”. Keluaran berikut membuktikan sebaliknya:
setTimeout(() => console.log("timeout 0 ms"), 0);
Promise.resolve().then(() => console.log("microtask"));
console.log("sinkron");Output yang Dihasilkan:
sinkron
microtask
timeout 0 msUrutannya tetap: kode sinkron dulu, microtask menyusul, dan callback setTimeout dengan delay 0 terakhir. Alasannya sama seperti di chapter Event Loop — delay 0 tetap mendaftarkan macrotask, dan macrotask hanya mendapat giliran setelah call stack kosong dan antrean microtask habis.
Loop Async: Menunggu Langkah demi Langkah #
Kebutuhan yang khas: memproses daftar langkah asinkron satu demi satu — misalnya menyapa pelanggan satu per satu dengan jeda, bukan sekaligus. Gabungan for-of dari section Collections dan await di dalam function async memberikan bentuknya:
function tunggu(ms, nilai) {
return new Promise((resolve) => setTimeout(() => resolve(nilai), ms));
}
async function sapaPelanggan(daftarNama) {
for (const nama of daftarNama) {
const sapaan = await tunggu(10, `Halo ${nama}`);
console.log(sapaan);
}
console.log("semua pelanggan dilayani");
}
sapaPelanggan(["Budi", "Siti", "Dewi"]);Output yang Dihasilkan:
Halo Budi
Halo Siti
Halo Dewi
semua pelanggan dilayaniSetiap putaran menunggu promise selesai sebelum lanjut ke nama berikutnya, sehingga urutan keluaran dijamin sama dengan urutan daftar. Pola ini menggantikan trik lama yang memakai setInterval untuk hal serupa: interval tidak bisa menunggu pekerjaan asinkron selesai, sehingga pekerjaan yang lambat bisa bertumpuk pada giliran berikutnya. Kalau langkahnya asinkron, loop dengan await adalah bentuk yang benar.
Untuk mengatur seberapa banyak pekerjaan yang berjalan sekaligus — bukan sekadar memproses berurutan — kita butuh pola concurrency. Itu bahasan chapter penutup section ini.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
pengatur-waktu.js
Unduh berkas// pengatur-waktu.js
// setTimeout, clearTimeout, setInterval, dan clearInterval.
// --- 1. setTimeout + clearTimeout: pengingat yang dibatalkan ---
const idPengingat = setTimeout(() => {
console.log("pengingat: ambil kopi Budi");
}, 20);
setTimeout(() => {
clearTimeout(idPengingat);
console.log("pengingat dibatalkan sebelum sempat berjalan");
}, 10);
// --- 2. setInterval + clearInterval: pengadukan berulang ---
let hitungan = 0;
const idPengaduk = setInterval(() => {
hitungan += 1;
console.log(`pengadukan ke-${hitungan}`);
if (hitungan === 3) {
clearInterval(idPengaduk);
console.log("pengadukan selesai");
}
}, 10);