Il existe une nouvelle API pour effectuer des requêtes à partir de JavaScript: fetch (). Existe-t-il un mécanisme intégré pour annuler ces demandes en vol?
fetch
prend désormais en charge un paramètre signal
à partir du 20 septembre 2017, mais tous les navigateurs ne semblent pas supporter cette atm .
C’est un changement que nous verrons très bientôt, et vous devriez donc pouvoir annuler une demande en utilisant un AbortController
s AbortSignal
.
Voici comment cela fonctionne:
Étape 1 : vous créez une AbortController
(pour l'instant je viens d'utiliser this )
const controller = new AbortController()
Étape 2 : Vous obtenez le signal AbortController
s comme ceci:
const signal = controller.signal
Étape 3 : Vous passez le signal
à récupérer comme suit:
fetch(urlToFetch, {
method: 'get',
signal: signal, // <------ This is our AbortSignal
})
Étape 4 : Abandonnez à chaque fois que vous devez:
controller.abort();
Voici un exemple de fonctionnement (fonctionne sur Firefox 57+):
<script>
// Create an instance.
const controller = new AbortController()
const signal = controller.signal
/*
// Register a listenr.
signal.addEventListener("abort", () => {
console.log("aborted!")
})
*/
function beginFetching() {
console.log('Now fetching');
var urlToFetch = "https://httpbin.org/delay/3";
fetch(urlToFetch, {
method: 'get',
signal: signal,
})
.then(function(response) {
console.log(`Fetch complete. (Not aborted)`);
}).catch(function(err) {
console.error(` Err: ${err}`);
});
}
function abortFetching() {
console.log('Now aborting');
// Abort.
controller.abort()
}
</script>
<h1>Example of fetch abort</h1>
<hr>
<button onclick="beginFetching();">
Begin
</button>
<button onclick="abortFetching();">
Abort
</button>
Je ne crois pas qu'il soit possible d'annuler une demande avec l'API d'extraction existante. Des discussions sont en cours à ce sujet sur le site https://github.com/whatwg/fetch/issues/27
Mise à jour de mai 2017: toujours pas de résolution. Les demandes ne peuvent pas être annulées. Plus de discussions sur https://github.com/whatwg/fetch/issues/447
https://developers.google.com/web/updates/2017/09/abortable-fetch
https://dom.spec.whatwg.org/#aborting-ongoing-activities
// setup AbortController
const controller = new AbortController();
// signal to pass to fetch
const signal = controller.signal;
// fetch as usual
fetch(url, { signal }).then(response => {
...
}).catch(e => {
// catch the abort if you like
if (e.name === 'AbortError') {
...
}
});
// when you want to abort
controller.abort();
fonctionne dans Edge 16 (2017-10-17), firefox 57 (2017-11-14), desktop safari 11.1 (2018-03-29), ios safari 11.4 (2018-03-29), chrome 67 (2018-05-29) et plus tard.
sur les anciens navigateurs, vous pouvez utiliser github's whatwg-fetch polyfill et AbortController polyfill . vous pouvez détecter les anciens navigateurs et utiliser les polyfills de manière conditionnelle , aussi:
import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'
import {fetch} from 'whatwg-fetch'
// use native browser implementation if it supports aborting
const abortableFetch = ('signal' in new Request('')) ? window.fetch : fetch
À compter de février 2018, fetch()
peut être annulé à l'aide du code ci-dessous sur Chrome (read tilisation de flux lisibles pour activer le support Firefox). Aucune erreur n'est générée pour que catch()
récupère, et il s'agit d'une solution temporaire jusqu'à ce que AbortController
soit complètement adopté.
fetch('YOUR_CUSTOM_URL')
.then(response => {
if (!response.body) {
console.warn("ReadableStream is not yet supported in this browser. See https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream")
return response;
}
// get reference to ReadableStream so we can cancel/abort this fetch request.
const responseReader = response.body.getReader();
startAbortSimulation(responseReader);
// Return a new Response object that implements a custom reader.
return new Response(new ReadableStream(new ReadableStreamConfig(responseReader)));
})
.then(response => response.blob())
.then(data => console.log('Download ended. Bytes downloaded:', data.size))
.catch(error => console.error('Error during fetch()', error))
// Here's an example of how to abort request once fetch() starts
function startAbortSimulation(responseReader) {
// abort fetch() after 50ms
setTimeout(function() {
console.log('aborting fetch()...');
responseReader.cancel()
.then(function() {
console.log('fetch() aborted');
})
},50)
}
// ReadableStream constructor requires custom implementation of start() method
function ReadableStreamConfig(reader) {
return {
start(controller) {
read();
function read() {
reader.read().then(({done,value}) => {
if (done) {
controller.close();
return;
}
controller.enqueue(value);
read();
})
}
}
}
}
Pour l’instant, il n’existe pas de solution adéquate, comme le dit @spro.
Toutefois, si vous avez une réponse en vol et utilisez ReadableStream, vous pouvez fermer le flux pour annuler la demande.
fetch('http://example.com').then((res) => {
const reader = res.body.getReader();
/*
* Your code for reading streams goes here
*/
// To abort/cancel HTTP request...
reader.cancel();
});