Open jrainlau opened 3 years ago
在最近的工作中,有一项内容是需要知道当前用户的网络情况以采取对应的展示策略。这块内容是我之前没有研究过的,正好趁此机会了解一下。
那么我们要怎样做才能获取到用户的网络速度呢?下面是调研到的几种方法。
window.navigator.connection
在 Chrome 浏览器种,我们可以使用 window.navigator.connection API 中的 downlink 属性来获取实时网速:
downlink
根据 MDN 文档的说法,该 downlink 属性是以每秒兆位为单位返回有效带宽估计值。比如当 downlink 的值是 5.0 的时候,理论下载速度可能是 5Mb/s。
遗憾的是,这个 API 仍然处于实验阶段,部分功能在 iOS 或者 Safari 上都是不可用的,我们需要找到另外一种方式去测试网速。
这也是一些测速网站常用的做法,比如这个爱测速。
它请求了部署在其服务器上的几个接口
来分别获得如下载速度、上传速度、网络延迟和网络抖动等数据。
我们可以通过阅读它的测速代码 speedtest_worker.min.js 来一探究竟。简单地来说,就是通过构造不同的 XHR 对象对接口进行请求,记录开始和结束的时间,最后换算成具体的数据。
这种部署服务的方式比较主流,但是实现成本较高。另外还有一点需要注意,如果接口挂了,可能就会走到 error 的逻辑,会误判为用户的网络中断了。
error
这是一种成本较低,也是非常通用的做法。我们可以让浏览器通过 GET 请求去获取一张既定大小的图片,分析获取图片所需的时间,即可换算成实际的下载速度。这种办法比第一小节的 window.navigator.connection.downlink 数据更准确,因为那个 API 的只是理论值,实际值还需要通过真正地去下载资源才能获取。
window.navigator.connection.downlink
附上实现的代码,可以看出这种方案确实最为经济实惠:
function testDownloadSpeed ({ url, size }) { return new Promise((resolve, reject) => { const img = new Image() img.src = `url?_t=${Math.random()}` // 加个时间戳以避免浏览器只发起一次请求 const startTime = new Date() img.onload = function () { const fileSize = size // 单位是 kb const endTime = new Date() const costTime = endTime - startTime const speed = fileSize / (endTime - startTime) * 1000 // 单位是 kb/s resolve({ speed, costTime }) } img.onerror = reject }) }
我们在浏览器中拿这张大小为 146kb 的图片 https://raw.githubusercontent.com/jrainlau/imghost/master/29e9103b4a6801aa42f8f08ef65ad51c%20(1).ytuxq1kbb4f.png 试一下:
https://raw.githubusercontent.com/jrainlau/imghost/master/29e9103b4a6801aa42f8f08ef65ad51c%20(1).ytuxq1kbb4f.png
输出的耗时和 Network 面板的基本吻合,且计算出来的下载速度也和上一节在 爱测速 得到的数据基本一致,因此可以得出这种方法靠谱的结论。
(完)
在最近的工作中,有一项内容是需要知道当前用户的网络情况以采取对应的展示策略。这块内容是我之前没有研究过的,正好趁此机会了解一下。
那么我们要怎样做才能获取到用户的网络速度呢?下面是调研到的几种方法。
一、通过
window.navigator.connection
API 获取网速在 Chrome 浏览器种,我们可以使用
window.navigator.connection
API 中的downlink
属性来获取实时网速:根据 MDN 文档的说法,该
downlink
属性是以每秒兆位为单位返回有效带宽估计值。比如当downlink
的值是 5.0 的时候,理论下载速度可能是 5Mb/s。遗憾的是,这个 API 仍然处于实验阶段,部分功能在 iOS 或者 Safari 上都是不可用的,我们需要找到另外一种方式去测试网速。
二、部署服务,通过请求接口来获取网速
这也是一些测速网站常用的做法,比如这个爱测速。
它请求了部署在其服务器上的几个接口
来分别获得如下载速度、上传速度、网络延迟和网络抖动等数据。
我们可以通过阅读它的测速代码 speedtest_worker.min.js 来一探究竟。简单地来说,就是通过构造不同的 XHR 对象对接口进行请求,记录开始和结束的时间,最后换算成具体的数据。
这种部署服务的方式比较主流,但是实现成本较高。另外还有一点需要注意,如果接口挂了,可能就会走到
error
的逻辑,会误判为用户的网络中断了。三、获取静态图片资源
这是一种成本较低,也是非常通用的做法。我们可以让浏览器通过 GET 请求去获取一张既定大小的图片,分析获取图片所需的时间,即可换算成实际的下载速度。这种办法比第一小节的
window.navigator.connection.downlink
数据更准确,因为那个 API 的只是理论值,实际值还需要通过真正地去下载资源才能获取。附上实现的代码,可以看出这种方案确实最为经济实惠:
我们在浏览器中拿这张大小为 146kb 的图片
https://raw.githubusercontent.com/jrainlau/imghost/master/29e9103b4a6801aa42f8f08ef65ad51c%20(1).ytuxq1kbb4f.png
试一下:输出的耗时和 Network 面板的基本吻合,且计算出来的下载速度也和上一节在 爱测速 得到的数据基本一致,因此可以得出这种方法靠谱的结论。
(完)