Frontend proqramlaşdırmasında ən çox rast gəlinən səhvlərdən biri async əməliyyatların lazımi anda dayandırılmamasıdır. İstifadəçi səhifədən çıxır, komponent unmount olur, yeni axtarış sorğusu köhnəsini əvəz edir – amma köhnə sorğu işləməyə davam edir. Nəticədə artıq mövcud olmayan state yenilənir və ya köhnə məlumat göstərilir. React'də bu, məşhur xəbərdarlıq mesajı ilə özünü göstərir: “Can't perform a React state update on an unmounted component”. Vanilla JS-də isə səssizcə köhnə məlumatlar səhifəyə düşür.
Race condition: real problem, real həll
Məsələn, istifadəçi axtarış qutusuna “re” yazıb sonra tez “rea” əlavə edir. Birinci sorğu hələ cavablanmayıb, ikincisi başlayır. Şəbəkə yavaşdırsa, “re” sorğusu “rea” sorğusundan gec cavablana bilər. O zaman setResults doğru nəticənin üzərinə köhnə nəticəni yazır – istifadəçi səhv məlumat görür. Heç bir xəbərdarlıq, heç bir səhv mesajı. Bu, nəzəri deyil, real bir problemdir – yavaş şəbəkədə, sürətli yazma zamanı və ya zəif cihazlarda asanlıqla təkrarlanır.
AbortController necə işləyir?
AbortController brauzerin daxili mexanizmidir – 2018-ci ildən bütün əsas brauzerlərdə mövcuddur. İş prinsipi sadədir: bir controller obyekti və bir signal yaradırsınız. Signalı fetch kimi abort-destəkləyən API-ə ötürürsünüz, sonra lazım olan anda abort() çağırırsınız. Bu, useEffect içərisində aşağıdakı kimi görünür:
useEffect(() => { const controller = new AbortController(); fetch(`/api/search?q=${query}`, { signal: controller.signal }) .then(r => r.json()) .then(data => setResults(data)) .catch(err => { if (err.name !== 'AbortError') throw err; }); return () => controller.abort(); }, [query]);Burada diqqət edilməli əsas məqam: catch blokunda AbortError-i udmaq vacibdir. Əks halda hər unmount zamanı error boundary'ə düşəcək. Eyni nümunə async/await ilə də işləyir – fərq yalnız sintaksisdədir.
Yalnız fetch üçün deyil
AbortController yalnız şəbəkə sorğuları üçün deyil. addEventListener API-i də signal qəbul edir. Eyni signal ilə bir neçə listener əlavə edib, bir abort() ilə hamısını silə bilərsiniz:
const controller = new AbortController(); const { signal } = controller; window.addEventListener('keydown', handler, { signal }); window.addEventListener('keyup', handler, { signal }); return () => controller.abort();Əvvəllər hər listener üçün ayrıca removeEventListener yazmaq lazım idi – indi bir sətir kifayətdir.
Nə vaxt istifadə etməli, nə vaxt yox?
- İstifadə edin: istifadəçi girişinə bağlı axtarış, səhifələmə, filtr, polling – useEffect yenidən işə düşən hər async əməliyyat.
- Atlayın: form göndərmə, ödəniş, mesaj göndərmə kimi fire-and-forget əməliyyatlar – istifadəçi səhifədən çıxsa belə sorğu tamamlansın.
- Unutmayın: abort yalnız klient tərəfdə işləyir – server sorğunu emal etməyə davam edir.
Xülasə: AbortController heç bir kitabxana, build plugin və ya yeni konsepsiya tələb etmir. Sadəcə bir konstruktor, bir signal və bir metod. Əgər useEffect içərisində fetch işlədirsinizsə və AbortController istifadə etmirsinizsə, race condition-unuz var – istifadəçi yəqin ki, bunu artıq görüb (flicker, köhnə nəticənin qısa müddətə görünməsi, izaholunmaz konsol xəbərdarlığı). İndi bunu izah edə bilərsiniz – və bir cleanup funksiyası yazmaq qədər zamanda düzəldə bilərsiniz.


