Seperti yang kita tahu, fetch
mengembalikan promise
dan Javascript secara umum tidak memiliki konsep untuk “membatalkan” sebuah janji (Promise
). Jadi, bagaimana kita bisa membatalkan fetch
yang sedang dijalankan? misalnya, jika tindakan pengguna pada situs kita mengindikasikan bahwa fetch
sudah tidak dibutuhkan lagi.
Terdapat objek bawaan khusus untuk tujuan ini: AbortContoller
. Metode tersebut dapat digunakan untuk membatalkan tidak hanya fetch
, tetapi tugas asingkron lainnya.
Penggunaannya sangat mudah:
Objek AbortController
Membuat sebuah pengontrol (controller)
let controller = new AbortController();
Pengontrol adalah objek yang sangat sederhana.
- Hanya memiliki satu metode
abort()
, - dan sebuah properti
signal
yang memungkinkan untuk menyetellistener
pada objek pengontrol.
Ketika abort()
dipanggil:
contoller.signal
mengeluarkan event"abort"
- Properti
controller.signal.aborted
menjadi bernilaitrue
Secara Umum, kita memiliki dua pihak dalam prosesnya:
- Satu pihak yang melaksanakan tindakan terntentu ketika operasi dibatalkan, itu menyetel listener pada
controller.signal
. - Satu pihak lainnya yang membatalkan: itu memanggil
controller.abort()
ketika diperlukan.
Berikut contoh lengkapnya (tanpa fetch
)
let controller = new AbortController();
let signal = controller.signal;
// Pihak yang melakukan tindakan tertentu ketika operasi dibatalkan
// mendapatkan objek "signal"
// dan menyetel 'listener' untuk memicu ketika controller.abort() dipanggil
signal.addEventListener('abort', () => alert('abort!'));
// Pihak lain yang membatalkan (penjelasnnya nanti)
controller.abort(); // gagalkan!
// Pemicu 'event' dan nilai 'signal.aborted' menjadi 'true'
alert(signal.aborted); // true
Seperti yang kita lihat, AbortController
hanyalah sarana untuk meneruskan event abort()
ketika dipanggil.
Kita dapat mengimplementasikan jenis event listener yang sama pada kode kita, walaupun tanpa objek AbortController
sama sekali.
Tetapi yang berharga adalah fetch
tahu bagaimana bekerja dengan objek AborController
, itu terintegrasi dengannya.
Menggunakan dengan fetch
Untuk bisa membatalkan fetch
, teruskan properti signal
dari AbortController
sebagai opsi fetch
:
let controller = new AbortController();
fetch(url, {
signal: controller.signal,
});
Metode fetch
mengetahui bagaimana cara bekerja dengan AbortController
. Itu akan mendengarkan (listen) event abort
pada properti signal
.
Sekarang, untuk membatalkannya, panggil controller.abort()
:
controller.abort();
Kita sudah selesai: fetch
mendapatkan event dari properti signal
dan membatalkan request.
Ketika fetch
dibatalkan, maka promise
akan ditolak dengan galat AboutError
, jadi kita dapat menanganinya. Misalnya dengan try ... catch
.
Berikut adalah contoh penuh untuk menggagalkan fetch
setelah 1 detik:
// gagalkan setelah satu detik
let controller = new AbortController();
setTimeout(() => controller.abort(), 1000);
try {
let response = await fetch('/article/fetch-abort/demo/hang', {
signal: controller.signal,
});
} catch (err) {
if (err.name == 'AbortError') {
// menangani ketika digagalkan
alert('Aborted!');
} else {
throw err;
}
}
AbortController dapat ditingkatkan (scalable)
AbortContoller
bersifat scalable, itu memungkinkan untuk membatalkan beberapa fetch
sekaligus.
Berikut adalah sketsa dari kode yang terdapat proses fetch
ke banyak urls
secara paralel, dan menggunakan pengontrol tunggal untuk membatalkan semua proses tersebut:
let urls = [...]; // daftar dari url yang akan diambil secara paralel
let controller = new AbortController();
// larik dari 'fetch promise'
let fetchJobs = urls.map(url => fetch(url, {
signal: controller.signal
}));
let results = await Promise.all(fetchJobs);
// jika controller.fetch() dipanggil dari tempat tertentu
// itu akan menggagalkan semua 'fetch'
Jika kita memiliki tugas asingkron kita sendiri yang berbeda dari fetch
, kita dapat menggunakan AbortController
tunggal untuk menghentikannya, bersama dengan metode fetch
.
Kita hanya perlu untuk listen
pada event abort
di tugas kita;
let urls = [...];
let controller = new AbortController();
let ourJob = new Promise((resolve, reject) => { // tugas kita
...
controller.signal.addEventListener('abort', reject);
});
let fetchJobs = urls.map(url => fetch(url, { // pemanggilan metode fetch
signal: controller.signal
}));
// Menunggu semua metode fetch dan tugas kita secara paralel
let results = await Promise.all([...fetchJobs, ourJob]);
// Jika controller.abort() dipanggil dari suatu tempat,
// itu menggagalkan semua metode fetch dan tugas kita
Kesimpulan
AbortController
adalah sebuah objek sederhana yang menghasilkan eventabort
pada propertisignal
ketika metodeabort()
dipanggil (dan juga menyetelsignal.aborted
menjaditrue
).fetch
terintegrasi dengannya: kita meneruskan propertisignal
sebagai opsi, dan kemudianfetch
mendengarkan event yang dihasilkanAbortController
. Jadi itu menjadi mungkin ketika ingin menggagalkan prosesfetch
.- Kita dapat menggunakan
AbortConntroller
pada kode kita. Interaksi "pemanggilanabort()
" → "Mendengarkan (listen) eventabort
" sederhana dan universal. Kita dapat menggunakannya walaupun tanpafetch
.