我有一个fetch-api POST请求:
fetch(url, {
method: 'POST',
body: formData,
credentials: 'include'
})
我想知道这个的默认超时时间是多少?我们如何将它设置为特定的值,比如3秒或不定秒?
我有一个fetch-api POST请求:
fetch(url, {
method: 'POST',
body: formData,
credentials: 'include'
})
我想知道这个的默认超时时间是多少?我们如何将它设置为特定的值,比如3秒或不定秒?
当前回答
fetchTimeout (url,options,timeout=3000) {
return new Promise( (resolve, reject) => {
fetch(url, options)
.then(resolve,reject)
setTimeout(reject,timeout);
})
}
其他回答
如果您没有在代码中配置超时,它将是浏览器的默认请求超时。
1) Firefox - 90秒
在Firefox URL字段中输入about:config。找到key network.http.connection-timeout对应的值
2) Chrome - 300秒
源
一个更简单的方法是在MDN中:https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal#aborting_a_fetch_operation_with_a_timeout
try {
await fetch(url, { signal: AbortSignal.timeout(5000) });
} catch (e) {
if (e.name === "TimeoutError") {
console.log('5000 ms timeout');
}
}
正确的错误处理技巧
正常的做法:
为了在大多数情况下增加超时支持,建议引入一个Promise实用函数,如下所示:
function fetchWithTimeout(resource, { signal, timeout, ...options } = {}) {
const controller = new AbortController();
if (signal != null) signal.addEventListener("abort", controller.abort);
const id = timeout != null ? setTimeout(controller.abort, timeout) : undefined;
return fetch(resource, {
...options,
signal: controller.signal
}).finally(() => {
if (id != null) clearTimeout(id);
});
}
调用控制器。abort或拒绝setTimeout回调函数中的承诺会扭曲堆栈跟踪。
这是次优的,因为如果需要对错误后日志进行分析,就必须在调用fetch方法的函数中添加带有日志消息的样板错误处理程序。
好专业知识:
为了保留错误及其堆栈跟踪,可以应用以下技术:
function sleep(ms = 0, signal) { return new Promise((resolve, reject) => { const id = setTimeout(() => resolve(), ms); signal?.addEventListener("abort", () => { clearTimeout(id); reject(); }); }); } async function fetch( resource, options ) { const { timeout, signal, ...ropts } = options ?? {}; const controller = new AbortController(); let sleepController; try { signal?.addEventListener("abort", () => controller.abort()); const request = nodeFetch(resource, { ...ropts, signal: controller.signal, }); if (timeout != null) { sleepController = new AbortController(); const aborter = sleep(timeout, sleepController.signal); const race = await Promise.race([aborter, request]); if (race == null) controller.abort(); } return request; } finally { sleepController?.abort(); } } (async () => { try { await fetchWithTimeout(new URL(window.location.href), { timeout: 5 }); } catch (error) { console.error("Error in test", error); } })();
基于无尽的回答,我创造了一个有用的效用函数。
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
}
});
使用c-promise2库,可取消的获取超时可能像这样(Live 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