如何用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开发的数独游戏代码
Oct 29 Javascript
javascript中的对象创建 实例附注释
Feb 08 Javascript
javascript结合fileReader 实现上传图片
Jan 30 Javascript
javascript随机显示背景图片的方法
Jun 18 Javascript
AngularJS 自定义指令详解及示例代码
Aug 17 Javascript
JS实现类似51job上的地区选择效果示例
Nov 17 Javascript
VueJS 集成 Medium Editor的示例代码 (自定义编辑器按钮)
Aug 24 Javascript
基于js Canvas实现二次贝塞尔曲线
Dec 25 Javascript
基于vue和websocket的多人在线聊天室
Feb 01 Javascript
详细分析vue表单数据的绑定
Jul 20 Javascript
JavaScript读取本地文件常用方法流程解析
Oct 12 Javascript
Element-ui Layout布局(Row和Col组件)的实现
Dec 06 Vue.js
浅谈JS的二进制家族
如何使用vue3打造一个物料库
Ajax常用封装库——Axios的使用
May 08 #Javascript
微信小程序用户授权最佳实践指南
vue完美实现el-table列宽自适应
详解JS WebSocket断开原因和心跳机制
May 07 #Javascript
如何用threejs实现实时多边形折射
You might like
smarty+adodb+部分自定义类的php开发模式
2006/12/31 PHP
基于empty函数的判断详解
2013/06/17 PHP
解析如何在PHP下载文件名中解决乱码的问题
2013/06/20 PHP
详解PHP中mb_strpos的使用
2018/02/04 PHP
JavaScript中的new的使用方法与注意事项
2007/05/16 Javascript
nodejs开发环境配置与使用
2014/11/17 NodeJs
超级简单的jquery操作表格方法
2014/12/15 Javascript
编写自己的jQuery提示框(Tip)插件
2015/02/05 Javascript
Bootstrap轮播加上css3动画,炫酷到底!
2015/12/22 Javascript
详解Angularjs中的依赖注入
2016/03/11 Javascript
JavaScript获取图片像素颜色并转换为box-shadow显示
2016/03/11 Javascript
webpack中CommonsChunkPlugin详细教程(小结)
2017/11/09 Javascript
webpack-dev-server远程访问配置方法
2018/02/22 Javascript
微信小程序本地存储实现每日签到、连续签到功能
2019/10/09 Javascript
vue-cli3项目配置eslint代码规范的完整步骤
2020/09/10 Javascript
node.js如何操作MySQL数据库
2020/10/29 Javascript
Node.js中的异步生成器与异步迭代详解
2021/01/31 Javascript
[01:20]2018DOTA2亚洲邀请赛总决赛战队LGD晋级之路
2018/04/07 DOTA
[01:14:19]NAVI vs Mineski 2019国际邀请赛淘汰赛 败者组BO1 8.20.mp4
2020/07/19 DOTA
详解Python的Django框架中的templates设置
2015/05/11 Python
Python中pygame的mouse鼠标事件用法实例
2015/11/11 Python
python技能之数据导出excel的实例代码
2017/08/11 Python
python 去除txt文本中的空格、数字、特定字母等方法
2018/07/24 Python
通过python实现随机交换礼物程序详解
2019/07/10 Python
Pytorch实现LSTM和GRU示例
2020/01/14 Python
keras之权重初始化方式
2020/05/21 Python
Python模拟登录和登录跳转的参考示例
2020/10/30 Python
Yahoo-PHP面试题2
2014/12/06 面试题
Unix如何在一行中运行多个命令
2015/05/29 面试题
销售演讲稿范文
2014/01/08 职场文书
环保建议书作文
2014/03/12 职场文书
亲属关系公证书
2014/04/08 职场文书
2014年文员工作总结
2014/11/18 职场文书
高二数学教学反思
2016/02/18 职场文书
selenium.webdriver中add_argument方法常用参数表
2021/04/08 Python
Win11更新失败并提示0xc1900101
2022/04/19 数码科技