Ich habe eine fetch-api
POST
Anfrage:
fetch(url, {
method: 'POST',
body: formData,
credentials: 'include'
})
Ich möchte wissen, wie hoch das Standardzeitlimit dafür ist. und wie können wir es auf einen bestimmten Wert wie 3 Sekunden oder unbestimmte Sekunden einstellen?
javascript
ajax
fetch-api
Akshay Lokur
quelle
quelle
.reject()
eines bereits gelösten Versprechens nichts bewirkt.Ich mag den sauberen Ansatz von diesem Kern mit Promise.race sehr
fetchWithTimeout.js
export default function (url, options, timeout = 7000) { return Promise.race([ fetch(url, options), new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), timeout) ) ]); }
main.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 })
quelle
fetch
Fehler auftritt . Dies kann behoben werden, indem der Fehler behandelt ( ) und erneut ausgelöst wird, wenn das Timeout noch nicht aufgetreten ist..catch
fetch
Mit dem AbortController können Sie Folgendes tun:
const controller = new AbortController(); const signal = controller.signal; const fetchPromise = fetch(url, {signal}); // 5 second timeout: const timeoutId = setTimeout(() => controller.abort(), 5000); fetchPromise.then(response => { // completed request before timeout fired // If you only wanted to timeout the request, not the response, add: // clearTimeout(timeoutId); })
quelle
Aufbauend auf der hervorragenden Antwort von Endless habe ich eine hilfreiche Utility-Funktion erstellt.
const fetchTimeout = (url, ms, { signal, ...options } = {}) => { const controller = new AbortController(); const promise = fetch(url, { signal: controller.signal, ...options }); if (signal) signal.addEventListener("abort", () => controller.abort()); const timeout = setTimeout(() => controller.abort(), ms); return promise.finally(() => clearTimeout(timeout)); };
const controller = new AbortController(); document.querySelector("button.cancel").addEventListener("click", () => controller.abort()); fetchTimeout("example.json", 5000, { signal: controller.signal }) .then(response => response.json()) .then(console.log) .catch(error => { if (error.name === "AbortError") { // fetch aborted either due to timeout or due to user clicking the cancel button } else { // network error or json parsing error } });
Hoffentlich hilft das.
quelle
Es gibt noch keine Timeout-Unterstützung in der Abruf-API. Aber es könnte erreicht werden, indem man es in ein Versprechen einwickelt.
für zB.
function fetchWrapper(url, options, timeout) { return new Promise((resolve, reject) => { fetch(url, options).then(resolve, reject); if (timeout) { const e = new Error("Connection timed out"); setTimeout(reject, timeout, e); } }); }
quelle
BEARBEITEN : Die Abrufanforderung wird weiterhin im Hintergrund ausgeführt und protokolliert höchstwahrscheinlich einen Fehler in Ihrer Konsole.
In der Tat ist der
Promise.race
Ansatz besser.Siehe diesen Link als Referenz Promise.race ()
Rennen bedeutet, dass alle Versprechen gleichzeitig ausgeführt werden und das Rennen beendet wird, sobald eines der Versprechen einen Wert zurückgibt. Daher wird nur ein Wert zurückgegeben . Sie können auch eine Funktion übergeben, die aufgerufen werden soll, wenn beim Abrufen eine Zeitüberschreitung auftritt.
fetchWithTimeout(url, { method: 'POST', body: formData, credentials: 'include', }, 5000, () => { /* do stuff here */ });
Wenn dies Ihr Interesse weckt, wäre eine mögliche Implementierung:
function fetchWithTimeout(url, options, delay, onTimeout) { const timer = new Promise((resolve) => { setTimeout(resolve, delay, { timeout: true, }); }); return Promise.race([ fetch(url, options), timer ]).then(response => { if (response.timeout) { onTimeout(); } return response; }); }
quelle
Sie können einen timeoutPromise-Wrapper erstellen
function timeoutPromise(timeout, err, promise) { return new Promise(function(resolve,reject) { promise.then(resolve,reject); setTimeout(reject.bind(null,err), timeout); }); }
Sie können dann jedes Versprechen einpacken
timeoutPromise(100, new Error('Timed Out!'), fetch(...)) .then(...) .catch(...)
Eine zugrunde liegende Verbindung wird nicht abgebrochen, aber Sie können ein Versprechen auslaufen lassen.
Referenz
quelle
Wenn Sie in Ihrem Code kein Zeitlimit konfiguriert haben, ist dies das Standard-Zeitlimit für Anforderungen Ihres Browsers.
1) Firefox - 90 Sekunden
Geben Sie das
about:config
Firefox-URL-Feld ein. Suchen Sie den Wert, der dem Schlüssel entsprichtnetwork.http.connection-timeout
2) Chrome - 300 Sekunden
Quelle
quelle
fetchTimeout (url,options,timeout=3000) { return new Promise( (resolve, reject) => { fetch(url, options) .then(resolve,reject) setTimeout(reject,timeout); }) }
quelle
Mit c-versprechen2 lib könnte der stornierbare Abruf mit Zeitüberschreitung wie folgt aussehen ( Live-jsfiddle-Demo ):
import CPromise from "c-promise2"; // npm package function fetchWithTimeout(url, {timeout, ...fetchOptions}= {}) { return new CPromise((resolve, reject, {signal}) => { fetch(url, {...fetchOptions, signal}).then(resolve, reject) }, timeout) } const chain = fetchWithTimeout("https://run.mocky.io/v3/753aa609-65ae-4109-8f83-9cfe365290f0?mocky-delay=10s", {timeout: 5000}) .then(request=> console.log('done')); // chain.cancel(); - to abort the request before the timeout
Dieser Code als npm-Paket cp-fetch
quelle