Magyar

Tanulja meg, hogyan használhatja a JavaScript AbortController-t aszinkron műveletek, például fetch kérések, időzítők hatékony megszakítására a tisztább és performánsabb kódért.

JavaScript AbortController: Az aszinkron műveletek megszakításának mesterfogásai

A modern webfejlesztésben az aszinkron műveletek mindenütt jelen vannak. Adatok lekérése API-kból, időzítők beállítása és felhasználói interakciók kezelése gyakran olyan kódot foglal magában, amely önállóan és potenciálisan hosszabb ideig fut. Vannak azonban olyan esetek, amikor ezeket a műveleteket még a befejezésük előtt meg kell szakítani. Itt jön a képbe a AbortController interfész a JavaScriptben. Tiszta és hatékony módot biztosít a megszakítási kérelmek jelzésére a DOM műveletek és más aszinkron feladatok számára.

Miért van szükség a megszakításra?

Mielőtt belemerülnénk a technikai részletekbe, értsük meg, miért fontos az aszinkron műveletek megszakítása. Vegyük fontolóra ezeket a gyakori forgatókönyveket:

Az AbortController és az AbortSignal bemutatása

Az AbortController interfészt az aszinkron műveletek megszakítási problémájának megoldására tervezték. Két kulcsfontosságú komponensből áll:

Alapvető használat: Fetch kérések megszakítása

Kezdjük egy egyszerű példával egy fetch kérés megszakítására:


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

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

// To cancel the fetch request:
controller.abort();

Magyarázat:

  1. Létrehozunk egy AbortController példányt.
  2. Lekérjük a hozzá tartozó AbortSignal-t a controller-ből.
  3. Átadjuk a signal-t a fetch opcióinak.
  4. Ha meg kell szakítanunk a kérést, meghívjuk a controller.abort()-ot.
  5. A .catch() blokkban ellenőrizzük, hogy a hiba AbortError-e. Ha igen, akkor tudjuk, hogy a kérés megszakadt.

Az AbortError kezelése

Amikor a controller.abort() meghívódik, a fetch kérés egy AbortError hibával fog elutasításra kerülni. Kulcsfontosságú, hogy ezt a hibát megfelelően kezeljük a kódban. Ennek elmulasztása kezeletlen promise elutasításokhoz és váratlan viselkedéshez vezethet.

Itt egy robusztusabb példa hibakezeléssel:


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(`HTTP error! Status: ${response.status}`);
    }
    const data = await response.json();
    console.log('Data:', data);
    return data;
  } catch (error) {
    if (error.name === 'AbortError') {
      console.log('Fetch aborted');
      return null; // Or throw the error to be handled further up
    } else {
      console.error('Fetch error:', error);
      throw error; // Re-throw the error to be handled further up
    }
  }
}

fetchData();

// To cancel the fetch request:
controller.abort();

Bevált gyakorlatok az AbortError kezelésére:

Időzítők megszakítása AbortSignal segítségével

Az AbortSignal használható a setTimeout vagy setInterval segítségével létrehozott időzítők megszakítására is. Ez egy kicsit több manuális munkát igényel, mivel a beépített időzítő funkciók nem támogatják közvetlenül az AbortSignal-t. Létre kell hozni egy egyéni függvényt, amely figyeli a megszakítási jelet, és törli az időzítőt, amikor az aktiválódik.


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('Timeout Aborted'));
    });
  });

  return timeoutPromise;
}

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


cancellableTimeout(() => {
  console.log('Timeout executed');
}, 2000, signal)
.then(() => console.log("Timeout finished successfully"))
.catch(err => console.log(err));

// To cancel the timeout:
controller.abort();

Magyarázat:

  1. A cancellableTimeout függvény egy visszahívást, egy késleltetést és egy AbortSignal-t fogad argumentumként.
  2. Beállít egy setTimeout-ot és elmenti az időzítő azonosítóját.
  3. Hozzáad egy eseményfigyelőt az AbortSignal-hoz, amely az abort eseményt figyeli.
  4. Amikor az abort esemény aktiválódik, az eseményfigyelő törli az időzítőt és elutasítja a promise-t.

Eseményfigyelők megszakítása

Az időzítőkhöz hasonlóan az AbortSignal segítségével megszakíthatók az eseményfigyelők is. Ez különösen akkor hasznos, ha el akarja távolítani egy lecsatolódó komponenshez társított eseményfigyelőket.


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

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

button.addEventListener('click', () => {
  console.log('Button clicked!');
}, { signal });

// To cancel the event listener:
controller.abort();

Magyarázat:

  1. Átadjuk a signal-t opcióként az addEventListener metódusnak.
  2. Amikor a controller.abort() meghívódik, az eseményfigyelő automatikusan eltávolításra kerül.

AbortController React komponensekben

A React-ben az AbortController segítségével megszakíthatja az aszinkron műveleteket, amikor egy komponens lecsatolódik. Ez elengedhetetlen a memóriaszivárgások és a lecsatolt komponensek frissítése által okozott hibák megelőzéséhez. Íme egy példa a useEffect hook használatával:


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(`HTTP error! Status: ${response.status}`);
        }
        const data = await response.json();
        setData(data);
      } catch (error) {
        if (error.name === 'AbortError') {
          console.log('Fetch aborted');
        } else {
          console.error('Fetch error:', error);
        }
      }
    }

    fetchData();

    return () => {
      controller.abort(); // Cancel the fetch request when the component unmounts
    };
  }, []); // Empty dependency array ensures this effect runs only once on mount

  return (
    
{data ? (

Data: {JSON.stringify(data)}

) : (

Loading...

)}
); } export default MyComponent;

Magyarázat:

  1. Létrehozunk egy AbortController-t a useEffect hook-on belül.
  2. Átadjuk a signal-t a fetch kérésnek.
  3. Visszaadunk egy tisztító függvényt a useEffect hook-ból. Ez a függvény akkor fog lefutni, amikor a komponens lecsatolódik.
  4. A tisztító függvényen belül meghívjuk a controller.abort()-ot a fetch kérés megszakításához.

Haladó felhasználási esetek

AbortSignal-ok láncolása

Néha előfordulhat, hogy több AbortSignal-t szeretne összeláncolni. Például lehet egy szülő komponens, amelynek meg kell szakítania a gyermekkomponensekben lévő műveleteket. Ezt egy új AbortController létrehozásával és annak jelének a szülő és a gyermek komponenseknek való átadásával érheti el.

AbortController használata külső könyvtárakkal

Ha egy olyan külső könyvtárat használ, amely nem támogatja közvetlenül az AbortSignal-t, lehet, hogy a kódját hozzá kell igazítania a könyvtár megszakítási mechanizmusához. Ez magában foglalhatja a könyvtár aszinkron függvényeinek saját függvényekbe való becsomagolását, amelyek kezelik az AbortSignal-t.

Az AbortController használatának előnyei

Böngészőkompatibilitás

Az AbortController széles körben támogatott a modern böngészőkben, beleértve a Chrome-ot, a Firefoxot, a Safarit és az Edge-et. A legfrissebb információkért ellenőrizze a kompatibilitási táblázatot az MDN Web Docs-on.

Polyfillek

Régebbi böngészők számára, amelyek natívan nem támogatják az AbortController-t, használhat egy polyfillt. A polyfill egy olyan kód, amely egy újabb funkció funkcionalitását biztosítja a régebbi böngészőkben. Számos AbortController polyfill érhető el online.

Összegzés

Az AbortController interfész egy hatékony eszköz az aszinkron műveletek kezelésére JavaScriptben. Az AbortController használatával tisztább, performánsabb és robusztusabb kódot írhat, amely elegánsan kezeli a megszakításokat. Akár adatokat kér le API-kból, időzítőket állít be, vagy eseményfigyelőket kezel, az AbortController segíthet javítani webalkalmazásai általános minőségét.

További olvasnivalók