javascript:如何对fetch()请求进行超时处理
如何对fetch()请求进行超时处理
当开发一个使用网络的应用程序时,首先要记住的规则是不要依赖网络。
网络是不可靠的,因为一个HTTP请求或响应可能会因为很多原因而失败。
- 用户处于离线状态
- DNS查询失败
- 服务器没有响应
- 服务器响应,但出现了错误
- 以及更多。
用户可以等待8秒来完成简单的请求。这就是为什么你需要对网络请求设置一个超时,并在8秒后通知用户网络问题。
我将向你展示如何使用setTimeout()
,中止控制器,以及fetch()
API来进行具有可配置超时时间的请求(包括有趣的演示!)。
1.默认的fetch()超时
默认情况下,fetch()
请求在浏览器指示的时间超时。在Chrome中,网络请求超时为300秒,而在Firefox中为90秒。
async function loadGames() {
const response = await fetch('/games');
// fetch() timeouts at 300 seconds in Chrome
const games = await response.json();
return games;
}
300秒甚至90秒都远远超过了用户对完成一个简单网络请求的期望。
在演示中,/games
URL被配置为在301秒内响应。点击加载游戏按钮开始请求,它将在300秒内超时(在Chrome中)。
2.给fetch()请求超时
fetch()
API本身不允许以编程方式取消一个请求。为了在所需的时间停止一个请求,你需要另外一个终止控制器。
下面的fetchWithTimeout()
是fetch()
的改进版,它可以创建具有可配置超时的请求。
async function fetchWithTimeout(resource, options = {}) {
const { timeout = 8000 } = options;
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);
const response = await fetch(resource, {
...options,
signal: controller.signal
});
clearTimeout(id);
return response;
}
首先,const { timeout = 8000 } = options
从options
对象中提取以毫秒为单位的超时参数(默认为8秒)。
const controller = new AbortController()
创建一个中止控制器的实例。这个控制器可以让你随意停止 的请求。注意,每一个请求都必须创建一个新的中止控制器,换句话说,控制器是不可重复使用的。fetch()
const id = setTimeout(() => controller.abort(), timeout)
启动一个计时功能。在 时间之后,如果计时函数没有被清除, 要中止(或取消)获取请求。timeout
controller.abort()
下一行await fetch(resource, { ...option, signal: controller.signal })
,正确地开始获取请求。注意分配给signal
属性的特殊controller.signal
值:它将fetch()
与中止控制器连接起来。
最后,clearTimeout(id)
,如果请求完成的速度比timeout
的时间快,则清除终止计时功能。
现在,这里是如何使用fetchWithTimeout()
。
async function loadGames() {
try {
const response = await fetchWithTimeout('/games', {
timeout: 6000
});
const games = await response.json();
return games;
} catch (error) {
// Timeouts if the request takes
// longer than 6 seconds
console.log(error.name === 'AbortError');
}
}
fetchWithTimeout()
(而不是简单的 )启动一个请求,在fetch()
时间-6秒内取消 timeout
。
如果对/games
的请求在6秒内还没有完成,那么这个请求就会被取消,并抛出一个超时错误。
你可以在catch
块内使用表达式error.name === 'AbortError'
,以确定是否有请求超时的情况发生。
打开演示,点击加载游戏按钮。对/games
的请求超时,因为它花费的时间超过了6秒。
3.总结
默认情况下,fetch()
的请求在浏览器设置的时间内超时。例如,在Chrome浏览器中,这个设置等于300秒。这比用户期望完成的简单网络请求要长得多。
在进行网络请求时,一个好的方法是配置一个大约8-10秒的请求超时。
如帖子中所示,使用setTimeout()
和中止控制器,你可以创建fetch()
请求,配置为在你愿意的时候超时。
检查浏览器对中止控制器的支持情况,因为截至2020年,它是一项实验性技术。也有一个polyfill。
请注意,如果不使用中止控制器,你就没有办法停止fetch()
的请求。不要使用这样的解决方案。
转载自:https://juejin.cn/post/7126043782172114951