Ma’lumki, fetch promise’ni qaytaradi. Va JavaScript’da umuman “promise’ni to’xtatish” tushunchasi yo’q. Unda davom etayotgan fetch’ni qanday bekor qilishimiz mumkin? Masalan, agar saytimizda foydalanuvchi harakatlari fetch endi kerak emasligini ko’rsatsa.
Bunday maqsadlar uchun maxsus o’rnatilgan obyekt mavjud: AbortController. U nafaqat fetch’ni, balki boshqa asinxron vazifalarni ham to’xtatish uchun ishlatilishi mumkin.
Foydalanish juda oddiy:
AbortController obyekti
Controller yarating:
let controller = new AbortController();
Controller juda oddiy obyekt.
- Uning bitta
abort()metodi bor, - Va bitta
signalxususiyati bor, u ustiga event listener’larini o’rnatish imkonini beradi.
abort() chaqirilganda:
controller.signal"abort"event’ini chiqaradi.controller.signal.abortedxususiyatitruebo’ladi.
Umuman olganda, jarayonda ikkita tomon bor:
- Bekor qilinadigan operatsiyani bajaradigan tomon, u
controller.signalustiga listener o’rnatadi. - Bekor qiladigan tomon: kerak bo’lganda
controller.abort()ni chaqiradi.
Mana to’liq misol (hali fetch bo’lmagan):
let controller = new AbortController();
let signal = controller.signal;
// Bekor qilinadigan operatsiyani bajaradigan tomon
// "signal" obyektini oladi
// va controller.abort() chaqirilganda ishga tushishi uchun listener o'rnatadi
signal.addEventListener('abort', () => alert("to'xtatildi!"));
// Boshqa tomon, bekor qiladigan (keyinchalik istalgan paytda):
controller.abort(); // to'xtatildi!
// Event ishga tushadi va signal.aborted true bo'ladi
alert(signal.aborted); // true
Ko’rib turganingizdek, AbortController faqat abort() chaqirilganda abort event’larini uzatish vositasidir.
Biz AbortController obyektisiz ham o’z kodimizda xuddi shunday event listening’ni amalga oshirishimiz mumkin.
Lekin qimmatli tomoni shundaki, fetch AbortController obyekti bilan qanday ishlashni biladi. U unda integratsiya qilingan.
fetch bilan ishlatish
fetch’ni bekor qilish uchun, AbortControllerning signal xususiyatini fetch opsiyasi sifatida bering:
let controller = new AbortController();
fetch(url, {
signal: controller.signal
});
fetch metodi AbortController bilan qanday ishlashni biladi. U signal ustidagi abort event’larini tinglaydi.
Endi to’xtatish uchun controller.abort() ni chaqiring:
controller.abort();
Tugadi: fetch signaldan event’ni oladi va so’rovni to’xtatadi.
Fetch to’xtatilganda, uning promise’si AbortError xatosi bilan rad etiladi, shuning uchun biz uni, masalan, try..catch da boshqarishimiz kerak.
Mana 1 soniyadan keyin to’xtatilgan fetch bilan to’liq misol:
// 1 soniyada to'xtatish
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') { // abort() ni boshqarish
alert("To'xtatildi!");
} else {
throw err;
}
}
AbortController miqyoslanadigan
AbortController miqyoslanadigan. U bir vaqtning o’zida bir nechta fetch’larni bekor qilish imkonini beradi.
Mana parallel ravishda ko’plab url’larni fetch qiladigan va ularning barchasini to’xtatish uchun bitta controller dan foydalanadigan kodning eskizi:
let urls = [...]; // parallel fetch qilinadigan url'lar ro'yxati
let controller = new AbortController();
// fetch promise'lari massivi
let fetchJobs = urls.map(url => fetch(url, {
signal: controller.signal
}));
let results = await Promise.all(fetchJobs);
// agar controller.abort() istalgan joydan chaqirilsa,
// u barcha fetch'larni to'xtatadi
Agar bizning fetchdan farq qiladigan o’z asinxron vazifalarimiz bo’lsa, fetch’lar bilan birga ularni to’xtatish uchun bitta AbortControllerdan foydalanishimiz mumkin.
Biz faqat o’z vazifalarimizda uning abort event’ini tinglashimiz kerak:
let urls = [...];
let controller = new AbortController();
let ourJob = new Promise((resolve, reject) => { // bizning vazifamiz
...
controller.signal.addEventListener('abort', reject);
});
let fetchJobs = urls.map(url => fetch(url, { // fetch'lar
signal: controller.signal
}));
// Fetch'lar va bizning vazifamizni parallel kutish
let results = await Promise.all([...fetchJobs, ourJob]);
// agar controller.abort() istalgan joydan chaqirilsa,
// u barcha fetch'lar va ourJob'ni to'xtatadi
Xulosa
AbortController–abort()metodi chaqirilganda o’ziningsignalxususiyatidaabortevent’ini yaratadigan oddiy obyekt (va shuningdeksignal.abortednitruega o’rnatadi).fetchu bilan integratsiyalashgan: bizsignalxususiyatini opsiya sifatida beramiz, so’ngrafetchuni tinglaydi, shuning uchunfetch’ni to’xtatish mumkin.- Biz
AbortControllerni o’z kodimizda ishlatishimiz mumkin. “abort()ni chaqirish” → “abortevent’ini tinglash” o’zaro ta’siri oddiy va universal. Biz uni hattofetchsiz ham ishlatishimiz mumkin.
Izohlar
<code>yorlig'ini ishlating, bir nechta satrlar uchun - ularni<pre>yorlig'i bilan o'rab qo'ying, 10 satrdan ortiq bo'lsa - sandbox (plnkr, jsbin, codepen…)