Načítání:Přerušit

Jak víme, fetch vrátí slib. A JavaScript obecně nemá žádný koncept „zrušení“ slibu. Jak tedy můžeme zrušit probíhající fetch ? Např. pokud akce uživatele na našem webu ukazují, že fetch už není potřeba.

Pro tyto účely existuje speciální vestavěný objekt:AbortController . Lze jej použít k přerušení nejen fetch , ale také další asynchronní úlohy.

Použití je velmi jednoduché:

Objekt AbortController

Vytvořte ovladač:

let controller = new AbortController();

Ovladač je extrémně jednoduchý objekt.

  • Má jednu metodu abort() ,
  • A jedna vlastnost signal který na něm umožňuje nastavit posluchače událostí.

Když abort() se jmenuje:

  • controller.signal vysílá "abort" událost.
  • controller.signal.aborted vlastnost se změní na true .

Obecně máme v procesu dvě strany:

  1. Ten, který provádí zrušitelnou operaci, nastaví posluchače na controller.signal .
  2. Ten, který se ruší:volá controller.abort() když je potřeba.

Zde je úplný příklad (bez fetch ještě):

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

// The party that performs a cancelable operation
// gets the "signal" object
// and sets the listener to trigger when controller.abort() is called
signal.addEventListener('abort', () => alert("abort!"));

// The other party, that cancels (at any point later):
controller.abort(); // abort!

// The event triggers and signal.aborted becomes true
alert(signal.aborted); // true

Jak vidíme, AbortController je pouze prostředkem k předání abort události při abort() se na to říká.

Stejný druh naslouchání události bychom mohli implementovat do našeho kódu sami, bez AbortController objekt.

Ale co je cenné, je fetch ví, jak pracovat s AbortController objekt. Je v něm integrován.

Použití s ​​načítáním

Aby bylo možné zrušit fetch , předejte signal vlastnost AbortController jako fetch možnost:

let controller = new AbortController();
fetch(url, {
  signal: controller.signal
});

fetch metoda ví, jak pracovat s AbortController . Bude poslouchat abort události na signal .

Nyní pro zrušení zavolejte controller.abort() :

controller.abort();

Hotovo:fetch získá událost z signal a zruší požadavek.

Když je načítání přerušeno, jeho příslib se odmítne s chybou AbortError , tak bychom to měli zvládnout, např. v try..catch .

Zde je úplný příklad s fetch přerušeno po 1 sekundě:

// abort in 1 second
let controller = new AbortController();
setTimeout(() => controller.abort(), 1000);

try {
  let response = await fetch('/article/fetch-abort/demo/hang', {
    signal: controller.signal
  });
} catch(err) {
  if (err.name == 'AbortError') { // handle abort()
    alert("Aborted!");
  } else {
    throw err;
  }
}

AbortController je škálovatelný

AbortController je škálovatelný. Umožňuje zrušit více načtení najednou.

Zde je náčrt kódu, který načítá mnoho urls paralelně a používá jediný ovladač k jejich zrušení:

let urls = [...]; // a list of urls to fetch in parallel

let controller = new AbortController();

// an array of fetch promises
let fetchJobs = urls.map(url => fetch(url, {
  signal: controller.signal
}));

let results = await Promise.all(fetchJobs);

// if controller.abort() is called from anywhere,
// it aborts all fetches

Pokud máme vlastní asynchronní úlohy, odlišné od fetch , můžeme použít jeden AbortController zastavit je společně s aporty.

Musíme jen poslouchat jeho abort událost v našich úkolech:

let urls = [...];
let controller = new AbortController();

let ourJob = new Promise((resolve, reject) => { // our task
  ...
  controller.signal.addEventListener('abort', reject);
});

let fetchJobs = urls.map(url => fetch(url, { // fetches
  signal: controller.signal
}));

// Wait for fetches and our task in parallel
let results = await Promise.all([...fetchJobs, ourJob]);

// if controller.abort() is called from anywhere,
// it aborts all fetches and ourJob

Shrnutí

  • AbortController je jednoduchý objekt, který generuje abort událost na jeho signal vlastnost při abort() je volána metoda (a také nastavuje signal.aborted na true ).
  • fetch integruje se s ním:předáme signal vlastnost jako možnost a poté fetch naslouchá, takže je možné přerušit fetch .
  • Můžeme použít AbortController v našem kódu. Volejte abort() " → "poslouchejte abort Interakce události“ je jednoduchá a univerzální. Můžeme jej použít i bez fetch .