如何用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 相关文章推荐
一个用js实现的页内搜索代码
May 23 Javascript
jQuery 性能优化指南(3)
May 21 Javascript
Google的跟踪代码 动态加载js代码方法应用
Nov 12 Javascript
extjs tabpanel限制选项卡数量实现思路及代码
Apr 02 Javascript
javascript中使用正则表达式清理table样式的代码
Apr 01 Javascript
JavaScript省市区三级联动菜单效果
Sep 21 Javascript
Jquery实现上下移动和排序代码
Oct 17 Javascript
原生JS版和jquery版实现checkbox的全选/全不选/点选/行内点选(Mr.Think)
Oct 29 Javascript
react-router v4如何使用history控制路由跳转详解
Jan 09 Javascript
angularJs复选框checkbox选中进行ng-show显示隐藏的方法
Oct 08 Javascript
微信小程序实现发送模板消息功能示例【通过openid推送消息给用户】
May 05 Javascript
vue实现短信验证码输入框
Apr 17 Javascript
浅谈JS的二进制家族
如何使用vue3打造一个物料库
Ajax常用封装库——Axios的使用
May 08 #Javascript
微信小程序用户授权最佳实践指南
vue完美实现el-table列宽自适应
详解JS WebSocket断开原因和心跳机制
May 07 #Javascript
如何用threejs实现实时多边形折射
You might like
ucenter通信原理分析
2015/01/09 PHP
PHP进程同步代码实例
2015/02/12 PHP
PHP实现163邮箱自动发送邮件
2016/03/29 PHP
Thinkphp5 自定义上传文件名的实现方法
2019/07/23 PHP
Bootstrap每天必学之下拉菜单
2015/11/25 Javascript
实例解析jQuery插件EasyUI最常用的表单验证规则
2015/11/29 Javascript
JavaScript动态创建div等元素实例讲解
2016/01/06 Javascript
基于javascript实现全国省市二级联动下拉选择菜单
2016/01/28 Javascript
超漂亮的Bootstrap 富文本编辑器summernote
2016/04/05 Javascript
使用JQuery 加载页面时调用JS的实现方法
2016/05/30 Javascript
微信小程序 WXML、WXSS 和JS介绍及详解
2016/10/08 Javascript
vue基于Element构建自定义树的示例代码
2017/09/19 Javascript
JavaScript模拟实现封装的三种方式及写法区别
2017/10/27 Javascript
js 索引下标之li集合绑定点击事件
2018/01/12 Javascript
bootstrap 点击空白处popover弹出框隐藏实例
2018/01/24 Javascript
JavaScript设计模式之调停者模式实例详解
2018/02/03 Javascript
jQuery实现鼠标响应式透明度渐变动画效果示例
2018/02/13 jQuery
vue自定义指令directive的使用方法
2019/04/07 Javascript
js定义类的方法示例【ES5与ES6】
2019/07/30 Javascript
layui 弹出删除确认界面的实例
2019/09/06 Javascript
微信小程序实现禁止分享代码实例
2019/10/19 Javascript
[01:03:41]DOTA2-DPC中国联赛 正赛 Dynasty vs XG BO3 第三场 2月2日
2021/03/11 DOTA
python编写暴力破解FTP密码小工具
2014/11/19 Python
Django实现快速分页的方法实例
2017/10/22 Python
对numpy.append()里的axis的用法详解
2018/06/28 Python
Python的条件表达式和lambda表达式实例
2019/01/31 Python
python交易记录整合交易类详解
2019/07/03 Python
对python 树状嵌套结构的实现思路详解
2019/08/09 Python
python使用布隆过滤器的实现示例
2020/08/20 Python
HTML5等待加载动画效果
2017/07/27 HTML / CSS
使用HTML5 IndexDB存储图像和文件的示例
2018/11/05 HTML / CSS
SHEIN台湾:购买最新流行女装服饰
2019/05/18 全球购物
美国沙龙美发产品购物网站:Hair.com by L’Oreal
2020/11/09 全球购物
澳大利亚Rockwear官网:女子瑜伽、健身和运动服
2021/01/26 全球购物
群众路线教育实践活动实施方案
2014/10/31 职场文书
小学生运动会广播
2015/08/19 职场文书