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:
- Lietotāja navigācija: Lietotājs uzsāk meklēšanas vaicājumu, izraisot API pieprasījumu. Ja viņš ātri pāriet uz citu lapu, pirms pieprasījums ir pabeigts, sākotnējais pieprasījums kļūst neatbilstošs un būtu jāatceļ, lai izvairītos no nevajadzīgas tīkla trafika un iespējamām blakusparādībām.
- Taimauta pārvaldība: Jūs iestatāt taimautu asinhronai operācijai. Ja operācija pabeidzas pirms taimauta termiņa beigām, jums vajadzētu atcelt taimautu, lai novērstu lieku koda izpildi.
- Komponentu noņemšana (unmounting): Front-end ietvaros, piemēram, React vai Vue.js, komponenti bieži veic asinhronus pieprasījumus. Kad komponents tiek noņemts, jebkuri ar to saistītie notiekošie pieprasījumi ir jāatceļ, lai izvairītos no atmiņas noplūdēm un kļūdām, ko izraisa atjaunināšana noņemtos komponentos.
- Resursu ierobežojumi: Resursu ierobežotās vidēs (piemēram, mobilajās ierīcēs, iegultajās sistēmās), nevajadzīgu operāciju atcelšana var atbrīvot vērtīgus resursus un uzlabot veiktspēju. Piemēram, atceļot liela attēla lejupielādi, ja lietotājs ritina garām šai lapas sadaļai.
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:
- AbortController: Šis objekts pārvalda atcelšanas signālu. Tam ir viena metode,
abort(), ko izmanto, lai signalizētu par atcelšanas pieprasījumu. - AbortSignal: Šis objekts apzīmē signālu, ka operācija ir jāpārtrauc. Tas ir saistīts ar
AbortControllerun tiek nodots asinhronajai operācijai, kurai jābūt atceļamai.
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:
- Mēs izveidojam
AbortControllerinstanci. - Mēs iegūstam saistīto
AbortSignalnocontroller. - Mēs nododam
signaluzfetchopcijām. - Ja mums ir nepieciešams atcelt pieprasījumu, mēs izsaucam
controller.abort(). .catch()blokā mēs pārbaudām, vai kļūda irAbortError. 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:
- Pārbaudiet kļūdas nosaukumu: Vienmēr pārbaudiet, vai
error.name === 'AbortError', lai nodrošinātu, ka apstrādājat pareizo kļūdas veidu. - Atgrieziet noklusējuma vērtību vai izmetiet kļūdu atkārtoti: Atkarībā no jūsu lietojumprogrammas loģikas, jūs varat atgriezt noklusējuma vērtību (piem.,
null) vai atkārtoti izmest kļūdu, lai to apstrādātu augstāk izsaukumu stekā. - Sakopiet resursus: Ja asinhronā operācija ir piešķīrusi kādus resursus (piemēram, taimerus, notikumu klausītājus), sakopiet tos
AbortErrorapstrādātājā.
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:
- Funkcija
cancellableTimeoutkā argumentus pieņem atzvanu (callback), aizkavi unAbortSignal. - Tā iestata
setTimeoutun saglabā taimauta ID. - Tā pievieno notikumu klausītāju
AbortSignal, kas klausāsabortnotikumu. - Kad tiek aktivizēts
abortnotikums, 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:
- Mēs nododam
signalkā opcijuaddEventListenermetodei. - 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:
- Mēs izveidojam
AbortControlleruseEffectāķa iekšpusē. - Mēs nododam
signaluzfetchpieprasījumu. - Mēs atgriežam sakopšanas funkciju no
useEffectāķa. Šī funkcija tiks izsaukta, kad komponents tiks noņemts. - 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
- Uzlabota veiktspēja: Nevajadzīgu operāciju atcelšana var samazināt tīkla trafiku, CPU lietojumu un atmiņas patēriņu, tādējādi uzlabojot veiktspēju, īpaši ierīcēs ar ierobežotiem resursiem.
- Tīrāks kods:
AbortControllernodrošina standartizētu un elegantu veidu, kā pārvaldīt atcelšanu, padarot jūsu kodu lasāmāku un uzturamāku. - Atmiņas noplūžu novēršana: Asinhrono operāciju atcelšana, kas saistītas ar noņemtiem komponentiem, novērš atmiņas noplūdes un kļūdas, ko izraisa atjaunināšana noņemtos komponentos.
- Labāka lietotāja pieredze: Neatbilstošu pieprasījumu atcelšana var uzlabot lietotāja pieredzi, novēršot novecojušas informācijas parādīšanu un samazinot uztverto latentumu.
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.