Eu tenho um fetch-api
POST
pedido:
fetch(url, {
method: 'POST',
body: formData,
credentials: 'include'
})
Quero saber qual é o tempo limite padrão para isso? e como podemos defini-lo para um valor específico como 3 segundos ou segundos indefinidos?
javascript
ajax
fetch-api
Akshay Lokur
fonte
fonte
.reject()
uma promessa que já foi resolvida não adianta nada.Eu realmente gosto da abordagem limpa desta essência 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 })
fonte
fetch
ocorrer um erro após o tempo limite. Isso pode ser resolvido manipulando (.catch
) afetch
falha e relançando se o tempo limite ainda não aconteceu.Usar uma solução de corrida de promessa deixará a solicitação suspensa e ainda consumirá largura de banda em segundo plano e reduzirá o máximo de solicitações simultâneas permitidas enquanto ainda está em processo.
Em vez disso, use o AbortController para realmente abortar a solicitação. Aqui está um exemplo
const controller = new AbortController() // 5 second timeout: const timeoutId = setTimeout(() => controller.abort(), 5000) fetch(url, { signal: controller.signal }).then(response => { // completed request before timeout fired // If you only wanted to timeout the request, not the response, add: // clearTimeout(timeoutId) })
AbortController também pode ser usado para outras coisas, não apenas para buscar, mas também para fluxos legíveis / graváveis. Funções mais novas (especialmente aquelas baseadas em promessa) usarão isso cada vez mais. NodeJS também implementou AbortController em seus streams / sistema de arquivos também. Eu sei que o bluetooth da web também está investigando isso
fonte
Com base na excelente resposta de Endless , criei uma função de utilidade ú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 ajude.
fonte
ainda não há suporte para tempo limite na API de busca. Mas isso poderia ser alcançado envolvendo-o em uma promessa.
por exemplo.
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); } }); }
fonte
EDITAR : A solicitação de busca ainda estará em execução em segundo plano e provavelmente registrará um erro em seu console.
Na verdade, a
Promise.race
abordagem é melhor.Veja este link para referência Promise.race ()
Corrida significa que todas as promessas serão realizadas ao mesmo tempo e a corrida será interrompida assim que uma das promessas retornar um valor. Portanto, apenas um valor será retornado . Você também pode passar uma função para chamar se a busca expirar.
fetchWithTimeout(url, { method: 'POST', body: formData, credentials: 'include', }, 5000, () => { /* do stuff here */ });
Se isso despertar seu interesse, uma possível implementação seria:
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; }); }
fonte
Você pode criar um wrapper timeoutPromise
function timeoutPromise(timeout, err, promise) { return new Promise(function(resolve,reject) { promise.then(resolve,reject); setTimeout(reject.bind(null,err), timeout); }); }
Você pode então quebrar qualquer promessa
timeoutPromise(100, new Error('Timed Out!'), fetch(...)) .then(...) .catch(...)
Na verdade, isso não cancelará uma conexão subjacente, mas permitirá que você expire uma promessa.
Referência
fonte
Se você não configurou o tempo limite em seu código, será o tempo limite de solicitação padrão do seu navegador.
1) Firefox - 90 segundos
Digite
about:config
no campo URL do Firefox. Encontre o valor correspondente à chavenetwork.http.connection-timeout
2) Chrome - 300 segundos
Fonte
fonte
fetchTimeout (url,options,timeout=3000) { return new Promise( (resolve, reject) => { fetch(url, options) .then(resolve,reject) setTimeout(reject,timeout); }) }
fonte
Usando c-promessa2 lib, a busca cancelável com tempo limite pode ser semelhante a esta ( demonstração ao vivo do jsfiddle ):
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 um pacote npm cp-fetch
fonte