我有一个fetch-api POST请求:
fetch(url, {
method: 'POST',
body: formData,
credentials: 'include'
})
我想知道这个的默认超时时间是多少?我们如何将它设置为特定的值,比如3秒或不定秒?
我有一个fetch-api POST请求:
fetch(url, {
method: 'POST',
body: formData,
credentials: 'include'
})
我想知道这个的默认超时时间是多少?我们如何将它设置为特定的值,比如3秒或不定秒?
当前回答
在取回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);
}
});
}
其他回答
使用AbortController和setTimeout;
const abortController = new AbortController();
let timer: number | null = null;
fetch('/get', {
signal: abortController.signal, // Content to abortController
})
.then(res => {
// response success
console.log(res);
if (timer) {
clearTimeout(timer); // clear timer
}
})
.catch(err => {
if (err instanceof DOMException && err.name === 'AbortError') {
// will return a DOMException
return;
}
// other errors
});
timer = setTimeout(() => {
abortController.abort();
}, 1000 * 10); // Abort request in 10s.
这是@fatcherjs/middleware-aborter中的一个片段。
通过使用fatcher,可以很容易地中止取回请求。
import { aborter } from '@fatcherjs/middleware-aborter';
import { fatcher, isAbortError } from 'fatcher';
fatcher({
url: '/bar/foo',
middlewares: [
aborter({
timeout: 10 * 1000, // 10s
onAbort: () => {
console.log('Request is Aborted.');
},
}),
],
})
.then(res => {
// Request success in 10s
console.log(res);
})
.catch(err => {
if (isAbortError(err)) {
//Run error when request aborted.
console.error(err);
}
// Other errors.
});
编辑:取回请求仍然在后台运行,很可能会在控制台中记录一个错误。
的确是应许。种族方法更好。
参见此链接以获取参考。
Race意味着所有promise将同时运行,一旦其中一个promise返回值,竞赛就会停止。 因此,只返回一个值。 如果取回超时,您也可以传递一个函数来调用。
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;
});
}
使用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
正确的错误处理技巧
正常的做法:
为了在大多数情况下增加超时支持,建议引入一个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); } })();
在取回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);
}
});
}