在开发使用网络的应用程序时,要记住的第一条规则是不要依赖网络。
网络不可靠,因为 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 })
正确启动获取请求。controller.signal
注意分配给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()
(而不是 simple fetch()
)启动一个在时间取消的请求timeout
- 6 秒。
如果请求/games
在 6 秒内未完成,则取消请求并引发超时错误。
您可以使用块error.name === 'AbortError'
内的表达式catch
来确定是否存在请求超时。
打开演示并单击加载游戏按钮。请求/games
超时,因为它需要超过 6 秒。
三、总结
默认情况下,fetch()
请求在浏览器设置的时间超时。例如,在 Chrome 中,此设置等于 300 秒。这比用户期望完成一个简单的网络请求要长得多。
发出网络请求时的一个好方法是将请求超时配置为大约 8 - 10 秒。
如帖子所示,使用setTimeout()
和中止控制器,您可以创建fetch()
配置为在您愿意时超时的请求。
检查中止控制器的浏览器支持,因为截至 2020 年它是一项实验性技术。它还有一个polyfill。
请注意,如果不使用中止控制器,您将无法停止fetch()
请求。不要使用这样的解决方案。
您还知道哪些有关网络请求的其他良好做法?
喜欢帖子吗?请分享!