Tengo una fetch-api
POST
solicitud:
fetch(url, {
method: 'POST',
body: formData,
credentials: 'include'
})
Quiero saber cuál es el tiempo de espera predeterminado para esto. y ¿cómo podemos establecerlo en un valor particular como 3 segundos o segundos indefinidos?
javascript
ajax
fetch-api
Akshay Lokur
fuente
fuente
.reject()
una promesa que ya se ha resuelto no hace nada.Realmente me gusta el enfoque limpio de esta esencia usando Promise.race
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 })
fuente
fetch
ocurre un error después del tiempo de espera. Esto se puede resolver manejando (.catch
) lafetch
falla y volviendo a lanzar si el tiempo de espera aún no ha ocurrido.Con AbortController , podrá hacer esto:
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); })
fuente
Basándome en la excelente respuesta de Endless , creé una función de utilidad útil.
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 } });
Espero que ayude.
fuente
todavía no hay soporte de tiempo de espera en la API de recuperación. Pero podría lograrse envolviéndolo en una promesa.
por ej.
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); } }); }
fuente
EDITAR : La solicitud de recuperación seguirá ejecutándose en segundo plano y lo más probable es que registre un error en su consola.
De hecho, el
Promise.race
enfoque es mejor.Vea este enlace para referencia Promise.race ()
Carrera significa que todas las promesas se ejecutarán al mismo tiempo y la carrera se detendrá tan pronto como una de las promesas devuelva un valor. Por lo tanto, solo se devolverá un valor . También puede pasar una función para llamar si se agota el tiempo de recuperación.
fetchWithTimeout(url, { method: 'POST', body: formData, credentials: 'include', }, 5000, () => { /* do stuff here */ });
Si esto despierta su interés, una posible implementación sería:
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; }); }
fuente
Puede crear un contenedor timeoutPromise
function timeoutPromise(timeout, err, promise) { return new Promise(function(resolve,reject) { promise.then(resolve,reject); setTimeout(reject.bind(null,err), timeout); }); }
Luego puedes envolver cualquier promesa
timeoutPromise(100, new Error('Timed Out!'), fetch(...)) .then(...) .catch(...)
En realidad, no cancelará una conexión subyacente, pero le permitirá agotar una promesa.
Referencia
fuente
Si no ha configurado el tiempo de espera en su código, será el tiempo de espera de solicitud predeterminado de su navegador.
1) Firefox - 90 segundos
Escriba
about:config
en el campo URL de Firefox. Encuentra el valor correspondiente a la clavenetwork.http.connection-timeout
2) Chrome: 300 segundos
Fuente
fuente
fetchTimeout (url,options,timeout=3000) { return new Promise( (resolve, reject) => { fetch(url, options) .then(resolve,reject) setTimeout(reject,timeout); }) }
fuente
Usando c-promise2 lib, la recuperación cancelable con tiempo de espera podría verse así ( demostración de jsfiddle en vivo ):
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
Este código como paquete npm cp-fetch
fuente