Română

Aflați cum să utilizați AbortController din JavaScript pentru a anula eficient operațiile asincrone, cum ar fi cererile fetch, cronometrele și multe altele, asigurând un cod mai curat și mai performant.

AbortController JavaScript: Stăpânirea Anulării Operațiilor Asincrone

În dezvoltarea web modernă, operațiile asincrone sunt omniprezente. Obținerea datelor de la API-uri, setarea cronometrelor și gestionarea interacțiunilor utilizatorilor implică adesea cod care rulează independent și potențial pentru o durată extinsă. Cu toate acestea, există scenarii în care trebuie să anulați aceste operații înainte de a fi finalizate. Aici intervine interfața AbortController din JavaScript. Aceasta oferă o modalitate curată și eficientă de a semnala cereri de anulare către operații DOM și alte sarcini asincrone.

Înțelegerea necesității anulării

Înainte de a intra în detalii tehnice, să înțelegem de ce anularea operațiilor asincrone este importantă. Luați în considerare aceste scenarii comune:

Introducere în AbortController și AbortSignal

Interfața AbortController este concepută pentru a rezolva problema anulării operațiilor asincrone. Aceasta constă din două componente cheie:

Utilizare de bază: Anularea cererilor Fetch

Să începem cu un exemplu simplu de anulare a unei solicitări fetch:


const controller = new AbortController();
const signal = controller.signal;

fetch('https://api.example.com/data', { signal })
  .then(response => {
    if (!response.ok) {
      throw new Error(`Eroare HTTP! Stare: ${response.status}`);
    }
    return response.json();
  })
  .then(data => {
    console.log('Date:', data);
  })
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('Fetch anulat');
    } else {
      console.error('Eroare Fetch:', error);
    }
  });

// Pentru a anula solicitarea fetch:
controller.abort();

Explicație:

  1. Cream o instanță AbortController.
  2. Obținem AbortSignal asociat de la controller.
  3. Transmitem signal opțiunilor fetch.
  4. Dacă trebuie să anulăm cererea, apelăm controller.abort().
  5. În blocul .catch(), verificăm dacă eroarea este un AbortError. Dacă este, știm că solicitarea a fost anulată.

Gestionarea AbortError

Când se apelează controller.abort(), solicitarea fetch va fi respinsă cu un AbortError. Este crucial să gestionați această eroare în mod corespunzător în codul dvs. Nerespectarea acestei cerințe poate duce la respingeri de promisiuni neprelucrate și comportament neașteptat.

Iată un exemplu mai robust cu gestionarea erorilor:


const controller = new AbortController();
const signal = controller.signal;

async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data', { signal });
    if (!response.ok) {
      throw new Error(`Eroare HTTP! Stare: ${response.status}`);
    }
    const data = await response.json();
    console.log('Date:', data);
    return data;
  } catch (error) {
    if (error.name === 'AbortError') {
      console.log('Fetch anulat');
      return null; // Sau aruncați eroarea pentru a fi gestionată mai departe
    } else {
      console.error('Eroare Fetch:', error);
      throw error; // Re-aruncați eroarea pentru a fi gestionată mai departe
    }
  }
}

fetchData();

// Pentru a anula solicitarea fetch:
controller.abort();

Cele mai bune practici pentru gestionarea AbortError:

Anularea cronometrelor cu AbortSignal

AbortSignal poate fi, de asemenea, utilizat pentru a anula cronometrele create cu setTimeout sau setInterval. Aceasta necesită un pic mai multă muncă manuală, deoarece funcțiile de cronometru încorporate nu acceptă direct AbortSignal. Trebuie să creați o funcție personalizată care ascultă semnalul de anulare și șterge cronometrul atunci când este declanșat.


function cancellableTimeout(callback, delay, signal) {
  let timeoutId;

  const timeoutPromise = new Promise((resolve, reject) => {
    timeoutId = setTimeout(() => {
      resolve(callback());
    }, delay);

    signal.addEventListener('abort', () => {
      clearTimeout(timeoutId);
      reject(new Error('Timp limită anulat'));
    });
  });

  return timeoutPromise;
}

const controller = new AbortController();
const signal = controller.signal;


cancellableTimeout(() => {
  console.log('Timp limită executat');
}, 2000, signal)
.then(() => console.log("Timpul limită s-a terminat cu succes"))
.catch(err => console.log(err));

// Pentru a anula timpul limită:
controller.abort();

Explicație:

  1. Funcția cancellableTimeout ia un callback, o întârziere și un AbortSignal ca argumente.
  2. Setează un setTimeout și stochează ID-ul de timp limită.
  3. Adaugă un ascultător de evenimente la AbortSignal care ascultă evenimentul abort.
  4. Când este declanșat evenimentul abort, ascultătorul de evenimente șterge timpul limită și respinge promisiunea.

Anularea ascultătorilor de evenimente

În mod similar cu cronometrele, puteți utiliza AbortSignal pentru a anula ascultătorii de evenimente. Acest lucru este deosebit de util atunci când doriți să eliminați ascultătorii de evenimente asociați cu o componentă care este demontată.


const controller = new AbortController();
const signal = controller.signal;

const button = document.getElementById('myButton');

button.addEventListener('click', () => {
  console.log('Butonul a fost apăsat!');
}, { signal });

// Pentru a anula ascultătorul de evenimente:
controller.abort();

Explicație:

  1. Transmitem signal ca opțiune la metoda addEventListener.
  2. Când se apelează controller.abort(), ascultătorul de evenimente va fi eliminat automat.

AbortController în componentele React

În React, puteți utiliza AbortController pentru a anula operațiile asincrone atunci când o componentă este demontată. Acest lucru este esențial pentru a preveni scurgerile de memorie și erorile cauzate de actualizarea componentelor demontate. Iată un exemplu care utilizează cârligul useEffect:


import React, { useState, useEffect } from 'react';

function MyComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    const controller = new AbortController();
    const signal = controller.signal;

    async function fetchData() {
      try {
        const response = await fetch('https://api.example.com/data', { signal });
        if (!response.ok) {
          throw new Error(`Eroare HTTP! Stare: ${response.status}`);
        }
        const data = await response.json();
        setData(data);
      } catch (error) {
        if (error.name === 'AbortError') {
          console.log('Fetch anulat');
        } else {
          console.error('Eroare Fetch:', error);
        }
      }
    }

    fetchData();

    return () => {
      controller.abort(); // Anulați cererea fetch atunci când componenta este demontată
    };
  }, []); // Matricea de dependență goală asigură că acest efect rulează o singură dată la montare

  return (
    
{data ? (

Date: {JSON.stringify(data)}

) : (

Se încarcă...

)}
); } export default MyComponent;

Explicație:

  1. Cream un AbortController în cadrul cârligului useEffect.
  2. Transmitem signal la cererea fetch.
  3. Returnăm o funcție de curățare din cârligul useEffect. Această funcție va fi apelată atunci când componenta este demontată.
  4. În interiorul funcției de curățare, apelăm controller.abort() pentru a anula cererea fetch.

Cazuri de utilizare avansate

Înlănțuirea AbortSignals

Uneori, este posibil să doriți să înlănțuiți mai multe AbortSignal împreună. De exemplu, este posibil să aveți o componentă părinte care trebuie să anuleze operațiile în componentele sale copil. Puteți realiza acest lucru creând un nou AbortController și transmitând semnalul său atât componentelor părinte, cât și componentelor copil.

Utilizarea AbortController cu biblioteci terțe

Dacă utilizați o bibliotecă terță care nu acceptă direct AbortSignal, este posibil să trebuiască să adaptați codul pentru a funcționa cu mecanismul de anulare al bibliotecii. Aceasta poate implica încapsularea funcțiilor asincrone ale bibliotecii în propriile funcții care gestionează AbortSignal.

Beneficiile utilizării AbortController

Compatibilitatea browserului

AbortController este pe larg suportat în browserele moderne, inclusiv Chrome, Firefox, Safari și Edge. Puteți verifica tabelul de compatibilitate pe MDN Web Docs pentru cele mai recente informații.

Polyfills

Pentru browserele mai vechi care nu acceptă nativ AbortController, puteți utiliza un polyfill. Un polyfill este o bucată de cod care oferă funcționalitatea unei caracteristici mai noi în browserele mai vechi. Există mai multe polyfill-uri AbortController disponibile online.

Concluzie

Interfața AbortController este un instrument puternic pentru gestionarea operațiilor asincrone în JavaScript. Folosind AbortController, puteți scrie un cod mai curat, mai performant și mai robust, care gestionează anularea cu eleganță. Indiferent dacă preluați date de la API-uri, setați cronometre sau gestionați ascultătorii de evenimente, AbortController vă poate ajuta să îmbunătățiți calitatea generală a aplicațiilor web.

Lecturi suplimentare