Latviešu

Uzziniet, kā ar JavaScript AbortController efektīvi atcelt asinhronas operācijas, piemēram, fetch pieprasījumus un taimerus, lai iegūtu tīrāku un ātrāku kodu.

JavaScript AbortController: Asinhrono operāciju atcelšanas apgūšana

Mūsdienu tīmekļa izstrādē asinhronas operācijas ir visuresošas. Datu iegūšana no API, taimeru iestatīšana un lietotāju mijiedarbības apstrāde bieži ietver kodu, kas darbojas neatkarīgi un potenciāli ilgu laiku. Tomēr ir scenāriji, kad šīs operācijas ir jāatceļ, pirms tās pabeigtas. Šeit nāk palīgā AbortController saskarne JavaScript valodā. Tā nodrošina tīru un efektīvu veidu, kā nosūtīt atcelšanas signālus DOM operācijām un citiem asinhroniem uzdevumiem.

Izpratne par nepieciešamību atcelt operācijas

Pirms iedziļināties tehniskajās detaļās, sapratīsim, kāpēc asinhrono operāciju atcelšana ir svarīga. Apsveriet šos izplatītos scenārijus:

Iepazīstinām ar AbortController un AbortSignal

AbortController saskarne ir paredzēta, lai atrisinātu asinhrono operāciju atcelšanas problēmu. Tā sastāv no diviem galvenajiem komponentiem:

Pamata lietojums: Fetch pieprasījumu atcelšana

Sāksim ar vienkāršu piemēru, kā atcelt fetch pieprasījumu:


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

Paskaidrojums:

  1. Mēs izveidojam AbortController instanci.
  2. Mēs iegūstam saistīto AbortSignal no controller.
  3. Mēs nododam signal uz fetch opcijām.
  4. Ja mums ir nepieciešams atcelt pieprasījumu, mēs izsaucam controller.abort().
  5. .catch() blokā mēs pārbaudām, vai kļūda ir AbortError. Ja tā ir, mēs zinām, ka pieprasījums tika atcelts.

AbortError apstrāde

Kad tiek izsaukts controller.abort(), fetch pieprasījums tiks noraidīts ar AbortError. Ir ļoti svarīgi pareizi apstrādāt šo kļūdu savā kodā. To neizdarot, var rasties neapstrādāti solījumu (promise) noraidījumi un neparedzēta uzvedība.

Šeit ir robustāks piemērs ar kļūdu apstrādi:


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

Labākā prakse AbortError apstrādei:

Taimeru atcelšana ar AbortSignal

AbortSignal var izmantot arī, lai atceltu taimerus, kas izveidoti ar setTimeout vai setInterval. Tas prasa nedaudz vairāk manuāla darba, jo iebūvētās taimera funkcijas tieši neatbalsta AbortSignal. Jums ir jāizveido pielāgota funkcija, kas klausās atcelšanas signālu un notīra taimeri, kad tas tiek aktivizēts.


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

Paskaidrojums:

  1. Funkcija cancellableTimeout kā argumentus pieņem atzvanu (callback), aizkavi un AbortSignal.
  2. Tā iestata setTimeout un saglabā taimauta ID.
  3. Tā pievieno notikumu klausītāju AbortSignal, kas klausās abort notikumu.
  4. Kad tiek aktivizēts abort notikums, notikumu klausītājs notīra taimeri un noraida solījumu (promise).

Notikumu klausītāju atcelšana

Līdzīgi kā ar taimeriem, jūs varat izmantot AbortSignal, lai atceltu notikumu klausītājus. Tas ir īpaši noderīgi, ja vēlaties noņemt notikumu klausītājus, kas saistīti ar komponentu, kas tiek noņemts.


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

Paskaidrojums:

  1. Mēs nododam signal kā opciju addEventListener metodei.
  2. Kad tiek izsaukts controller.abort(), notikumu klausītājs tiks automātiski noņemts.

AbortController React komponentos

React vidē varat izmantot AbortController, lai atceltu asinhronas operācijas, kad komponents tiek noņemts. Tas ir būtiski, lai novērstu atmiņas noplūdes un kļūdas, ko izraisa atjaunināšana noņemtos komponentos. Šeit ir piemērs, izmantojot useEffect āķi (hook):


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;

Paskaidrojums:

  1. Mēs izveidojam AbortController useEffect āķa iekšpusē.
  2. Mēs nododam signal uz fetch pieprasījumu.
  3. Mēs atgriežam sakopšanas funkciju no useEffect āķa. Šī funkcija tiks izsaukta, kad komponents tiks noņemts.
  4. Sakopšanas funkcijas iekšpusē mēs izsaucam controller.abort(), lai atceltu fetch pieprasījumu.

Papildu lietošanas gadījumi

AbortSignal saķēdēšana

Dažreiz var rasties nepieciešamība saķēdēt vairākus AbortSignal. Piemēram, vecākkomponentam var būt nepieciešams atcelt operācijas savos bērnkomponentos. To var panākt, izveidojot jaunu AbortController un nododot tā signālu gan vecākkomponentam, gan bērnkomponentiem.

AbortController izmantošana ar trešo pušu bibliotēkām

Ja izmantojat trešās puses bibliotēku, kas tieši neatbalsta AbortSignal, jums var nākties pielāgot savu kodu, lai tas darbotos ar bibliotēkas atcelšanas mehānismu. Tas var ietvert bibliotēkas asinhrono funkciju ietīšanu savās funkcijās, kas apstrādā AbortSignal.

AbortController izmantošanas priekšrocības

Pārlūku saderība

AbortController ir plaši atbalstīts modernajos pārlūkos, ieskaitot Chrome, Firefox, Safari un Edge. Jūs varat pārbaudīt saderības tabulu MDN Web Docs, lai iegūtu jaunāko informāciju.

Polifili (Polyfills)

Vecākiem pārlūkiem, kas dabiski neatbalsta AbortController, varat izmantot polifilu. Polifils ir koda daļa, kas nodrošina jaunākas funkcijas funkcionalitāti vecākos pārlūkos. Tiešsaistē ir pieejami vairāki AbortController polifili.

Noslēgums

AbortController saskarne ir spēcīgs rīks asinhrono operāciju pārvaldībai JavaScript valodā. Izmantojot AbortController, jūs varat rakstīt tīrāku, veiktspējīgāku un robustāku kodu, kas graciozi apstrādā atcelšanu. Neatkarīgi no tā, vai jūs iegūstat datus no API, iestatāt taimerus vai pārvaldāt notikumu klausītājus, AbortController var palīdzēt uzlabot jūsu tīmekļa lietojumprogrammu vispārējo kvalitāti.

Papildu lasāmviela