1. 需求概述
web页面在很多场景下需要获取当前网络状态做一些对应的操作。如:
-
网络慢的时候加载较小的资源,反之加载高清资源
-
切换网络的时候给用户一些提示
下面给出两种获取网络状态的解决方案
2. 方案一(Network Information API)
2.1 获取和监听网络状态
2.1.1 主要用的是navigator的connection属性,如下:
| downlink | 估算的下行速度/带宽,单位Mbps | |
|---|---|---|
| effectiveType | 当前的网络连接类型,可枚举值:slow-2g、2g、3g、4g | 使用最近观察到的往返时间和下行链路值的组合来确定的。 |
| onchange | 回调函数,在网络状态发生改变后执行 | |
| rtt | 估算的往返时间,单位ms | 四舍五入到最接近的25毫秒的倍数 |
| saveData | 是否打开数据保护模式 |
2.1.2 获取和监听网络状态的改变
const onConnectionChange = () => {
const { downlink, effectiveType, rtt, saveData } = navigator.connection;
console.log(`估算的下行速度/带宽:${downlink}Mb/s`);
console.log(`有效的网络连接类型:${effectiveType}`);
console.log(`估算的往返时间:${rtt}ms`);
console.log(`打开/请求数据保护模式:${saveData}`);
}
navigator.connection.addEventListener('change', onConnectionChange);
用浏览器的开发者工具的network模拟网络切换测试效果,如下:
通过navigator.connection可以判断出online,fast 3g,slow 3g,和offline,这四种状态下的effectiveType分别为4g,3g,2g,4g(rtt,downlink均为0)。
rtt、downlink比effectiveType更加具象且更能反映当前网络的真实情况;
| 网络状况 | rtt(ms) | downlink(Mbit/s) |
|---|---|---|
| online | 100 | 2.2 |
| fast 3g | 600 | 1.55 |
| slow 3g | 2150 | 0.4 |
| offline | 0 | 0 |
2.2 获取和监听网络连接、断开状态
- 通过navigator.connection中的属性downlink === 0Mb/s 且 rtt === 0ms时作为网络断开状态
- 通过navigator.onLine获取(无法及时获取真实网络连接状态)
// 上线(连网)监听:网络连接上时会触发online事件
window.addEventListener('online', () => {
console.log(navigator.onLine);
})
// 下线(断网)监听:网络连接断开时会触发offline事件
window.addEventListener('offline', () => {
console.log(navigator.onLine);
})
2.3 判断网络是否可用
2.2中,只是使用浏览器自身的能力来简单判断网络是否可用;对于局域网中是否真的可以连接网络,需要真实的发起一次网络请求,通过请求结果来判断。
以下是一个使用navigator.onLine和主动发起网络请求的方式,判断网络是否正常的函数的示例。这个函数首先会检查navigator.onLine的值,如果这个值为false,那么函数会立即返回网络不可用。如果这个值为true,函数会进一步发起一个网络请求以验证网络是否真的可用。
const checkNetworkStatus = (url = 'https://www.baidu.com') => {
return (
new Promise() <boolean > ((resolve) => {
if (!navigator.onLine) {
resolve(false);
} else {
fetch(url, { mode: 'no-cors' })
.then(() => resolve(true))
.catch((error) => resolve(false))
}
})
);
}
3. 方案二
做一个通用的测速接口,这里直接在服务器端放置一个5Mb大小的图片文件,前端fetch图片地址:
- 请求从发起到响应的时间差作为延迟;
- 请求从发起到等待输出文件流的时间差作为请求时间,结合文件流大小计算出下行速度/带宽;
注意:这里要用图片文件,不能用文本文件,因为一般服务端对文本内容会压缩后传输,但实际上拿到的文件内存大小不变,导致计算带宽值不准确。
4. 浏览器兼容性
Chrome 61及以上版本支持,Edge 79及以上版本支持,IE、Safari浏览器不支持,在不支持的浏览器或版本中,可以降级使用方案二替代。