Fetch API délai d'attente de la demande?
J'ai un fetch-api
POST
demande:
fetch(url, {
method: 'POST',
body: formData,
credentials: 'include'
})
Je veux savoir quel est le délai d'attente par défaut pour cela? et comment pouvons-nous fixer à une valeur particulière comme 3 secondes ou indéterminée secondes?
6 réponses
Il n'a pas de valeur par défaut spécifiée; la spécification ne traite pas du tout des délais d'attente.
Vous pouvez implémenter votre propre wrapper de délai d'attente pour les promesses en général:
// Rough implementation. Untested.
function timeout(ms, promise) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
reject(new Error("timeout"))
}, ms)
promise.then(resolve, reject)
})
}
timeout(1000, fetch('/hello')).then(function(response) {
// process response
}).catch(function(error) {
// might be a timeout error
})
Comme décrit dans https://github.com/github/fetch/issues/175 Commentaire de https://github.com/mislav
J'aime vraiment l'approche propre de cettegist en utilisant Promise.course
va chercher le temps mort.js
export default function (url, options, timeout = 7000) {
return Promise.race([
fetch(url, options),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('timeout')), timeout)
)
]);
}
principal.js
import fetch from './fetchWithTimeout'
// call as usual or with timeout as 3rd argument
fetch('http://google.com', options, 5000) // throw after max 5 seconds timeout error
.then((result) => {
// handle result
})
.catch((e) => {
// handle errors and timeout error
})
Il n'y a pas encore de prise en charge du délai d'attente dans l'API fetch. Mais cela pourrait être réalisé en l'enveloppant dans une promesse.
Pour par exemple.
function fetchWrapper(url, options, timeout) {
return new Promise((resolve, reject) => {
fetch(url, options).then(resolve).catch(reject);
if (timeout) {
const e = new Error("Connection timed out");
setTimeout(reject, timeout, e);
}
});
}
En utilisant la syntaxe abort, vous pourrez faire:
const controller = new AbortController();
const signal = controller.signal;
const fetchPromise = fetch(url, {signal});
// 5 second timeout:
const timeoutId = setTimeout(() => controller.abort(), 5000);
const response = await fetchPromise;
Si vous vouliez seulement temporiser la requête, pas la réponse, ajoutez:
clearTimeout(timeoutId);
// …
EDIT : la requête fetch sera toujours en cours d'exécution en arrière-plan et enregistrera probablement une erreur dans votre console.
En effet la promesse.la course approche est la meilleure.
Voir ce lien pour référence Promesse.course()
Course signifie que toutes les Promesses d'exécuter en même temps, et la course s'arrêtera dès que l'une des promesses renvoie une valeur. Par conséquent, seule valeur sera retournée. Vous pouvez également passer une fonction à appeler si le fetch fois sur.
fetchWithTimeout(url, {
method: 'POST',
body: formData,
credentials: 'include',
}, 5000, () => { /* do stuff here */ });
Si cela vous intéresse, une implémentation possible serait:
function fetchWithTimeout(url, options, delay, onTimeout) {
const timer = new Promise((resolve) => {
setTimeout(resolve, delay, {
timeout: true,
});
});
return Promise.race([
fetch(path, request),
timer
]).then(response) {
if (response.timeout) {
onTimeout();
}
return response;
}
}
Vous pouvez créer un wrapper timeoutPromise
function timeoutPromise(timeout, err, promise) {
return new Promise(function(resolve,reject) {
promise.then(resolve,reject);
setTimeout(reject.bind(null,err), timeout);
});
}
Vous pouvez ensuite envelopper toute promesse
timeoutPromise(100, new Error('Timed Out!'), fetcn(...))
.then(...)
.catch(...)
Il n'annulera pas réellement une connexion sous-jacente mais vous permettra de temporiser une promesse.
Référence