Čeština

Naučte se, jak efektivně rušit asynchronní operace jako fetch požadavky, časovače a další pomocí JavaScript AbortController pro čistší a výkonnější kód.

JavaScript AbortController: Zvládnutí rušení asynchronních operací

V moderním webovém vývoji jsou asynchronní operace všudypřítomné. Získávání dat z API, nastavování časovačů a zpracování interakcí s uživatelem často zahrnují kód, který běží nezávisle a potenciálně po delší dobu. Existují však scénáře, kdy je potřeba tyto operace zrušit před jejich dokončením. Zde přichází na pomoc rozhraní AbortController v JavaScriptu. Poskytuje čistý a efektivní způsob, jak signalizovat požadavky na zrušení operací DOM a jiných asynchronních úloh.

Pochopení potřeby rušení operací

Než se ponoříme do technických detailů, pojďme si vysvětlit, proč je rušení asynchronních operací důležité. Zvažte tyto běžné scénáře:

Představení AbortController a AbortSignal

Rozhraní AbortController je navrženo k řešení problému rušení asynchronních operací. Skládá se ze dvou klíčových komponent:

Základní použití: Rušení Fetch požadavků

Začněme jednoduchým příkladem zrušení fetch požadavku:


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();

Vysvětlení:

  1. Vytvoříme instanci AbortController.
  2. Získáme přidružený AbortSignal z controlleru.
  3. Předáme signal do možností fetch.
  4. Pokud potřebujeme požadavek zrušit, zavoláme controller.abort().
  5. V bloku .catch() kontrolujeme, zda je chyba typu AbortError. Pokud ano, víme, že požadavek byl zrušen.

Zpracování AbortError

Když je zavoláno controller.abort(), fetch požadavek bude zamítnut s chybou AbortError. Je klíčové tuto chybu ve vašem kódu správně ošetřit. Pokud tak neučiníte, může to vést k neošetřeným zamítnutím promise a neočekávanému chování.

Zde je robustnější příklad se zpracováním chyb:


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();

Osvědčené postupy pro zpracování AbortError:

Rušení časovačů pomocí AbortSignal

AbortSignal lze také použít k rušení časovačů vytvořených pomocí setTimeout nebo setInterval. To vyžaduje trochu více manuální práce, protože vestavěné funkce časovačů přímo nepodporují AbortSignal. Musíte vytvořit vlastní funkci, která naslouchá signálu pro přerušení a vyčistí časovač, když je spuštěn.


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();

Vysvětlení:

  1. Funkce cancellableTimeout přijímá jako argumenty callback, zpoždění a AbortSignal.
  2. Nastaví setTimeout a uloží ID časovače.
  3. Přidá posluchač událostí k AbortSignal, který naslouchá události abort.
  4. Když je událost abort spuštěna, posluchač událostí vyčistí časovač a zamítne promise.

Rušení posluchačů událostí

Podobně jako u časovačů můžete použít AbortSignal k rušení posluchačů událostí. To je zvláště užitečné, když chcete odstranit posluchače událostí spojené s komponentou, která je odpojována.


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();

Vysvětlení:

  1. Předáme signal jako volbu metodě addEventListener.
  2. Když je zavoláno controller.abort(), posluchač událostí bude automaticky odstraněn.

AbortController v React komponentách

V Reactu můžete použít AbortController k rušení asynchronních operací při odpojování komponenty. To je zásadní pro zabránění únikům paměti a chybám způsobeným aktualizací odpojených komponent. Zde je příklad s použitím useEffect hooku:


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;

Vysvětlení:

  1. Vytvoříme AbortController uvnitř useEffect hooku.
  2. Předáme signal do fetch požadavku.
  3. Z useEffect hooku vracíme čistící funkci. Tato funkce bude zavolána, když se komponenta odpojí.
  4. Uvnitř čistící funkce voláme controller.abort() pro zrušení fetch požadavku.

Pokročilé případy použití

Řetězení AbortSignalů

Někdy můžete chtít zřetězit více AbortSignalů dohromady. Například můžete mít rodičovskou komponentu, která potřebuje zrušit operace ve svých dceřiných komponentách. Toho můžete dosáhnout vytvořením nového AbortControlleru a předáním jeho signálu jak rodičovské, tak dceřiným komponentám.

Použití AbortController s knihovnami třetích stran

Pokud používáte knihovnu třetí strany, která přímo nepodporuje AbortSignal, možná budete muset přizpůsobit svůj kód tak, aby pracoval s mechanismem rušení dané knihovny. To může zahrnovat zabalení asynchronních funkcí knihovny do vašich vlastních funkcí, které zpracovávají AbortSignal.

Výhody použití AbortController

Kompatibilita s prohlížeči

AbortController je široce podporován v moderních prohlížečích, včetně Chrome, Firefox, Safari a Edge. Aktuální informace můžete zkontrolovat v tabulce kompatibility na MDN Web Docs.

Polyfilly

Pro starší prohlížeče, které nativně nepodporují AbortController, můžete použít polyfill. Polyfill je kousek kódu, který poskytuje funkcionalitu novější funkce ve starších prohlížečích. Na internetu je k dispozici několik polyfillů pro AbortController.

Závěr

Rozhraní AbortController je mocný nástroj pro správu asynchronních operací v JavaScriptu. Použitím AbortControlleru můžete psát čistší, výkonnější a robustnější kód, který elegantně zpracovává rušení operací. Ať už získáváte data z API, nastavujete časovače nebo spravujete posluchače událostí, AbortController vám může pomoci zlepšit celkovou kvalitu vašich webových aplikací.

Další čtení