У меня есть fetch-api
POST
просьба:
fetch(url, {
method: 'POST',
body: formData,
credentials: 'include'
})
Я хочу знать, какой тайм-аут по умолчанию для этого? и как мы можем установить его на определенное значение, например 3 секунды или неопределенные секунды?
javascript
ajax
fetch-api
Акшай Локур
источник
источник
.reject()
уже выполненного обещания ничего не делает.Мне очень нравится чистый подход от этой сущности , используя 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 })
источник
fetch
ошибка происходит по истечении тайм-аута. Это может быть решено обработкой (.catch
)fetch
ошибки и повторным вызовом, если тайм-аут еще не наступил.Используя AbortController , вы сможете сделать это:
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); })
источник
Основываясь на отличном ответе Endless , я создал полезную служебную функцию.
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 } });
Надеюсь, это поможет.
источник
в API выборки пока нет поддержки тайм-аута. Но этого можно достичь, обернув его обещанием.
например, для
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); } }); }
источник
РЕДАКТИРОВАТЬ : запрос на выборку по-прежнему будет выполняться в фоновом режиме и, скорее всего, будет регистрировать ошибку в вашей консоли.
Действительно
Promise.race
подход лучше.См. Эту ссылку для справки Promise.race ()
Гонка означает, что все обещания будут выполняться одновременно, и гонка остановится, как только одно из обещаний вернет значение. Следовательно, будет возвращено только одно значение . Вы также можете передать функцию для вызова, если время выборки истекло.
fetchWithTimeout(url, { method: 'POST', body: formData, credentials: 'include', }, 5000, () => { /* do stuff here */ });
Если это вас заинтересует, возможная реализация:
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; }); }
источник
Вы можете создать оболочку timeoutPromise
function timeoutPromise(timeout, err, promise) { return new Promise(function(resolve,reject) { promise.then(resolve,reject); setTimeout(reject.bind(null,err), timeout); }); }
Затем вы можете обернуть любое обещание
timeoutPromise(100, new Error('Timed Out!'), fetch(...)) .then(...) .catch(...)
На самом деле это не отменяет базовое соединение, но позволит вам отсрочить выполнение обещания.
Справка
источник
Если вы не настроили тайм-аут в своем коде, это будет тайм-аут запроса по умолчанию для вашего браузера.
1) Firefox - 90 секунд
Введите
about:config
URL-адрес Firefox. Найдите значение, соответствующее ключуnetwork.http.connection-timeout
2) Хром - 300 секунд
Источник
источник
fetchTimeout (url,options,timeout=3000) { return new Promise( (resolve, reject) => { fetch(url, options) .then(resolve,reject) setTimeout(reject,timeout); }) }
источник
При использовании c-обещания2 lib отменяемая выборка с тайм-аутом может выглядеть так ( живая демонстрация 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
Этот код как пакет npm cp-fetch
источник