如何用JavaScipt测网速


Posted in Javascript onMay 09, 2021

前言

事情是这样的,最近尝试写一个通过判断当前网速,从而在前端控制范围请求去分步请求一个大型文件的库。这个东东我现在一行代码都还没写,除了突然发现这个需求的思路有些不太实际之外,另一个原因是我突然问自己——前端要怎么判断网速啊?? ? !

前端判断网速的原理总结

(注:下面求的网速单位默认为KB/S)通过查阅相关资料,我发现思路主要是分为以下几种:

1.通过img加载或者发起Ajax请求计算网速

通过请求一个和服务端同域的文件,例如图片等,在前端开始请求和收到响应两个时间点分别通过Date.now标记start和end,因为Date.now得出的是1970年1月1日(UTC)到当前时间经过的毫秒数,所以我们通过end - start求出时间差(ms),然后通过计算:

文件大小(KB) * 1000 /( end -start )

就可以计算出网速了(KB/S)。

而请求文件又有两种方法:通过img加载或者AJAX加载:

  • 通过创建img对象,设置onload监听回调,然后指定src, 一旦指定src,图片资源就会加载,完成时onload回调就会调用,我们可以根据时机分别标记start和end。
  • 通过AJAX进行请求,即创建XHR对象,在onreadystatechange回调里,判断当readystate = 4时候加载完成,根据时机分别标记start和end。

2.window.navigator.connection.downlink网速查询

我们还可以通过一些H5的先进API去实现,例如这里我们可以使用的是window.navigator.connection.downlink 去查询,但是正如你所知道的是,这类API都是一副德性,即老生常谈的兼容性问题,所以我们一般都是作为一种预备的手段,通过能力检测,能用就用它,不能用就通过别的方法。而且需要注意downlink的单位是mbps,转化成KB/S的公式是

navigator.connection.downlink * 1024 / 8

乘1024可以理解,为什么后面要除8呢?这是因为mbps里的b指的是bit(比特),KB/s里面的B指的是Byte(字节),1字节(b)=8比特(bit),所以需要除个8

3. 一般来说,通过请求文件测算网速

单次可能会有误差,所以我们可以请求多次并计算均值。

前端判断网速的方法及其优缺点

  • img加载测速:借助img对象加载测算网速。优点:没有跨域带来的问题。缺点:(1)要自己测文件大小并提供参数fileSize,(2)文件必须为图片 (3)文件大小不能灵活控制
  • Ajax测速: 通过Ajax测算网速。 优点: (1)不用提供文件大小参数,因为可以从response首部获得(2)测试的文件不一定要是图片,且数据量能灵活控制。缺点:跨域问题
  • downlink测速: 通过navigator.connection.downlink读取网速。优点:不需要任何参数。缺点:1.兼容性很有问题,2.带宽查询不是实时的,具有分钟级别的时间间隔
  • 综合实现:先尝试采用downlink测速,否则多次AJAX测速并求平均值

img加载测速

function getSpeedWithImg(imgUrl, fileSize) {
    return new Promise((resolve, reject) => {
        let start = null;
        let end = null;
        let img = document.createElement('img');
        start = new Date().getTime();
        img.onload = function (e) {
            end = new Date().getTime();
            const speed = fileSize * 1000 / (end - start)
            resolve(speed);
        }
        img.src = imgUrl;
    }).catch(err => { throw err });
}

Ajax测速

function getSpeedWithAjax(url) {
    return new Promise((resolve, reject) => {
        let start = null;
        let end = null;
        start = new Date().getTime();
        const xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                end = new Date().getTime();
                const size = xhr.getResponseHeader('Content-Length') / 1024;
                const speed = size * 1000 / (end - start)
                resolve(speed);
            }
        }
        xhr.open('GET', url);
        xhr.send();
    }).catch(err => { throw err });
}

downlink测速

function getSpeedWithDnlink() {
    // downlink测算网速
    const connection = window.navigator.connection;
    if (connection && connection.downlink) {
        return connection.downlink * 1024 / 8;
    }
}

综合测速

function getNetSpeed(url, times) {
    // downlink测算网速
    const connection = window.navigator.connection;
    if (connection && connection.downlink) {
        return connection.downlink * 1024 / 8;
    }
    // 多次测速求平均值
    const arr = [];
    for (let i = 0; i < times; i++) {
        arr.push(getSpeedWithAjax(url));
    }
    return Promise.all(arr).then(speeds => {
        let sum = 0;
        speeds.forEach(speed => {
            sum += speed;
        });
        return sum / times;
    })
}

以上代码我发了一个npm包,可以通过下载

npm i network-speed-test

使用方式

import * from 'network-speed-test';
getSpeedWithImg("https://s2.ax1x.com/2019/08/13/mPJ2iq.jpg", 8.97).then(
    speed => {
        console.log(speed);
    }
)

getSpeedWithAjax('./speed.jpg').then(speed => {
    console.log(speed);
});

getNetSpeed('./speed.jpg', 3).then(speed => {
    console.log(speed);
});

getSpeedWithDnlink();

npm包地址

https://www.npmjs.com/package/network-speed-test

Github地址

https://github.com/penghuwan/network-speed-test

以上就是如何用JavaScipt测网速的详细内容,更多关于用JavaScipt测网速的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
jquery $.ajax()取xml数据的小问题解决方法
Nov 20 Javascript
关于jQuery参考实例2.0 用jQuery选择元素
Apr 07 Javascript
js调试系列 控制台命令行API使用方法
Jun 18 Javascript
Node.js开源应用框架HapiJS介绍
Jan 14 Javascript
javascript中call,apply,bind函数用法示例
Dec 19 Javascript
vue2项目使用sass的示例代码
Jun 28 Javascript
JavaScript指定断点操作实例教程
Sep 18 Javascript
使用vue-cli脚手架工具搭建vue-webpack项目
Jan 14 Javascript
Easyui 关闭jquery-easui tab标签页前触发事件的解决方法
Apr 28 jQuery
jquery.tagsinput.js实现记录checkbox勾选的顺序
Sep 21 jQuery
js实现蒙版效果
Jan 11 Javascript
nestjs中异常过滤器Exceptionfilter的具体使用
Feb 07 Javascript
浅谈JS的二进制家族
如何使用vue3打造一个物料库
Ajax常用封装库——Axios的使用
May 08 #Javascript
微信小程序用户授权最佳实践指南
vue完美实现el-table列宽自适应
详解JS WebSocket断开原因和心跳机制
May 07 #Javascript
如何用threejs实现实时多边形折射
You might like
Yii获取当前url和域名的方法
2015/06/08 PHP
iis 7下安装laravel 5.4环境的方法教程
2017/06/14 PHP
PHP通过文件路径获取文件名的实例代码
2018/10/14 PHP
JQuery 初体验(建议学习jquery)
2009/04/25 Javascript
xml 封装与解析(javascript和C#中)
2009/07/26 Javascript
js去字符串前后空格5种实现方法及比较
2013/04/03 Javascript
使用js实现按钮控制文本框加1减1应用于小时+分钟
2013/12/09 Javascript
原生JS获取元素集合的子元素宽度实例
2016/12/14 Javascript
JavaScript操作文件_动力节点Java学院整理
2017/06/30 Javascript
vue checkbox 全选 数据的绑定及获取和计算方法
2018/02/09 Javascript
解决Vue.js由于延时显示了{{message}}引用界面的问题
2018/08/25 Javascript
vue中动态添加class类名的方法
2018/09/05 Javascript
ES6中异步对象Promise用法详解
2019/07/31 Javascript
js实现小星星游戏
2020/03/23 Javascript
vue实现淘宝购物车功能
2020/04/20 Javascript
[01:53]3.19 DOTA2发布会 现场精彩Coser表演
2014/03/25 DOTA
python基础教程之lambda表达式使用方法
2014/02/12 Python
Python中的闭包详细介绍和实例
2014/11/21 Python
介绍Python中的文档测试模块
2015/04/28 Python
初步认识Python中的列表与位运算符
2015/10/12 Python
python利用MethodType绑定方法到类示例代码
2017/08/27 Python
Python3数据库操作包pymysql的操作方法
2018/07/16 Python
[原创]Python入门教程3. 列表基本操作【定义、运算、常用函数】
2018/10/30 Python
python实现在一个画布上画多个子图
2020/01/19 Python
解决Tensorflow 使用时cpu编译不支持警告的问题
2020/02/03 Python
python和go语言的区别是什么
2020/07/20 Python
python飞机大战游戏实例讲解
2020/12/04 Python
美国户外生活方式品牌:Eddie Bauer
2016/12/28 全球购物
Can a struct inherit from another class? (结构体能继承类吗)
2014/07/22 面试题
运动会演讲稿50字
2014/08/25 职场文书
放射科岗位职责
2015/02/14 职场文书
2016十一国庆节感言
2015/12/09 职场文书
你对自己的信用报告有过了解吗?
2019/07/09 职场文书
vue-cropper组件实现图片切割上传
2021/05/27 Vue.js
vscode中使用npm安装babel的方法
2021/08/02 Javascript
在Docker容器中部署SQL Server
2022/04/11 Servers