我有一个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);
})
}
其他回答
使用承诺竞争解决方案将使请求挂起,仍然在后台消耗带宽,并降低在处理过程中所允许的最大并发请求。
相反,使用AbortController实际中止请求,下面是一个例子
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)
})
您也可以使用新添加的AbortSignal.timeout(5000)…但是现在大多数浏览器都没有很好地实现它。现在所有的绿色环境都有这个。您将失去手动关闭请求的控制。上传和下载都必须在5秒内完成
// a polyfill for it would be:
AbortSignal.timeout ??= function timeout(ms) {
const ctrl = new AbortController()
setTimeout(() => ctrl.close(), ms)
return ctrl.signal
}
fetch(url, { signal: AbortSignal.timeout(5000) })
AbortController也可以用于其他事情,不仅是获取,还可以用于可读/可写流。越来越多的新函数(特别是基于承诺的函数)将越来越多地使用它。NodeJS也在它的流/文件系统中实现了AbortController。我知道网络蓝牙也在研究它。现在它也可以与addEventListener选项一起使用,并在信号结束时停止监听
编辑:取回请求仍然在后台运行,很可能会在控制台中记录一个错误。
的确是应许。种族方法更好。
参见此链接以获取参考。
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;
});
}
下面是一个使用NodeJS的SSCCE,它将在1000ms后超时:
import fetch from 'node-fetch';
const controller = new AbortController();
const timeout = setTimeout(() => {
controller.abort();
}, 1000); // will time out after 1000ms
fetch('https://www.yourexample.com', {
signal: controller.signal,
method: 'POST',
body: formData,
credentials: 'include'
}
)
.then(response => response.json())
.then(json => console.log(json))
.catch(err => {
if(err.name === 'AbortError') {
console.log('Timed out');
}}
)
.finally( () => {
clearTimeout(timeout);
});
如果您没有在代码中配置超时,它将是浏览器的默认请求超时。
1) Firefox - 90秒
在Firefox URL字段中输入about:config。找到key network.http.connection-timeout对应的值
2) Chrome - 300秒
源
更新,因为我最初的答案有点过时,我建议使用像这里实现的中止控制器:https://stackoverflow.com/a/57888548/1059828或看看这个非常好的帖子解释中止控制器与fetch:我如何取消HTTP fetch()请求?
过时的原答案:
我非常喜欢使用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
// throw after max 5 seconds timeout error
fetch('http://google.com', options, 5000)
.then((result) => {
// handle result
})
.catch((e) => {
// handle errors and timeout error
})