你的 app 是不是在线状态? 10 行代码就可以靠谱的判断是否真的在线
你的 app 是不是在线状态? 10 行代码就可以靠谱的判断是否真的在线
我们通常期望我们的 app 一直是有网可用的,但这不现实。
当人们在飞机上,进入隧道,网络太烂,或者自身关掉了网络。根据你用户的需要,你的 app 应该停用吗?
如果你想要你的app 能正常工作,你需要一种可靠的方式判断 app 是否断开了网络以便为你的用户提供更好的用户体验
下面用 10 行 JS 代码搞定
浏览器
在写代码之前让我们先了解一些浏览器的基本情况
浏览器有一个属性叫 navigator.onLine 它会根据浏览器状态直接返回 true 或 false.
function isOnline () {
return window.navigator.onLine
}
https://developer.mozilla.org/zh-CN/docs/Web/API/Navigator/onLine
所以,这就搞定了吗?, 由于它的工作方式,你只能相信它为 false 的状态,但不能信它为 true 的状态
如何判断你联网的状态?
由于 navigator 的工作方式,我们可以知道是否掉线了,但是否联网却不一定
当我们的设备连拉网络时 navigator 返回 true 但这并不意味着我们成功连接了互联网,这是两回事儿。
你首先本能的会想到发一个请求到随机的某个网站看看能否成功。
但是发一个什么样的请求呢?请求什么样的资源 🤔
找一个完美的请求方法 ✨
检测网络状态是个常用的功能,这个请求应该尽量的小,这样更快且更少的消耗带宽资源。
为了找到可用的请求, 我们可以看看不同的 HTTP 请求方法, 显然 HEAD 方法比较秀(TRACE 实际上可能更好,但 fetch 还不支持)
HEAD 请求跟一个 GET 请求非常像,但不会得到回复数据,只有 HEADers. 对于我们只希望检测网络是否可用来说足够了,我们并不需要关心具体返回了什么数据 。
应该向哪里发送请求
发什么样的请求我们有了,但应该发往哪里?
你首先本能的就会想到把它发送到某个在线服务器或网站。 比如 google.com? 但你尝试后肯定会碰到跨域请求的错误。
这并不意外, Google (所有其它网站) 默认都不允许接收任意网站发来的请求。
下一个选项是将你自己的服务器设置为允许你这个app的请求
但对一个简单检测网络联接来说就太过了,一个好的开发者应该是一个要多懒有多懒的人。
所以又回到了起点, CORS 跨域访问错误。
CORS 的目的是阻止非同域名下的不安全请求。 所以有没有可能发送这个请求到你自己的 域下呢?
答案是肯定的! 并且你可以自动获取你自己的域 window.location.origin
async function isOnline () {
if (!window.navigator.onLine) return false
const response = await fetch(
window.location.origin,
{ method: 'HEAD' },
)
return response.ok
}
现在你可以 ping 你自己的站并等待回复, 但问题是由于我们发送的是同一个 URL 请求, 你的浏览器会缓存这个请求导致我们的方法不起作用。
所以最后一个小技巧是为我们的请求加一个随机的参数!
这个对结果不会产生影响,并且由于每次请求都是不同的URL 这会阻止浏览器对我们的请求进行缓存。
还要感谢浏览器内建的 URL 类,我们不需要手动拼接字符串。
下面是最终的代码,且包含了一些错误处理
getRandomString () {
return Math.random().toString(36).substring(2, 15)
}
async function isOnline () {
if (!window.navigator.onLine) return false
// avoid CORS errors with a request to your own origin
const url = new URL(window.location.origin)
// random value to prevent cached responses
url.searchParams.set('rand', getRandomString())
try {
const response = await fetch(
url.toString(),
{ method: 'HEAD' },
)
return response.ok
} catch {
return false
}
}
这给了我们一个更可靠的检测网络状态的方法,但它缺少了一些可配置项。
特别是我们只能检测同一个 URL。 它很好,但如果你想要 ping 自己的服务器或需要理低的延迟呢?
另外,它只会在主动调用时运行一次, 给它添加一个回调可能会更有用,或者添一些加监听。
你可以添加 online 或 offline 网络状态的监听...
window.addEventListener('online', () => console.log('online'))
window.addEventListener('offline', () => console.log('offline'))
上面的代码很简单,你有更复杂的需求可以自己扩展
注:转载请注明出处博客园:王二狗Sheldon池中物 (willian12345@126.com)

浙公网安备 33010602011771号