如何用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选择头像并实时显示的代码
Jun 27 Javascript
JavaScript常用的弹出广告及背投广告实现方法
Feb 06 Javascript
jQuery固定元素插件scrolltofixed使用指南
Apr 21 Javascript
javascript 常见功能汇总
Jun 11 Javascript
详解Angular开发中的登陆与身份验证
Jul 27 Javascript
jQuery实现根据生日计算年龄 星座 生肖
Nov 23 Javascript
实现div滚动条默认最底部以及默认最右边的示例代码
Nov 15 Javascript
浅析vue中常见循环遍历指令的使用 v-for
Apr 18 Javascript
Bootstrap 模态框自定义点击和关闭事件详解
Aug 10 Javascript
layui 数据表格+分页+搜索+checkbox+缓存选中项数据的方法
Sep 21 Javascript
vue调用微信JSDK 扫一扫,相册等需要注意的事项
Jan 03 Vue.js
使用原生javascript开发计算器实例代码
Feb 21 Javascript
浅谈JS的二进制家族
如何使用vue3打造一个物料库
Ajax常用封装库——Axios的使用
May 08 #Javascript
微信小程序用户授权最佳实践指南
vue完美实现el-table列宽自适应
详解JS WebSocket断开原因和心跳机制
May 07 #Javascript
如何用threejs实现实时多边形折射
You might like
德生PL660的电路分析和打磨
2021/03/02 无线电
ecshop 订单确认中显示省市地址信息的方法
2010/03/15 PHP
PHP+Apache实现二级域名之间共享cookie的方法
2019/07/24 PHP
Js基础学习资料
2010/11/23 Javascript
js判断一个元素是否为另一个元素的子元素的代码
2012/03/21 Javascript
jquery多选项卡效果实例代码(附效果图)
2013/03/23 Javascript
ComboBox 和 DateField 在IE下消失的解决方法
2013/08/30 Javascript
常用的JavaScript验证正则表达式汇总
2013/11/26 Javascript
Javascript中常见的校验如域名、手机、邮箱等等
2014/01/02 Javascript
Jquery EasyUI中弹出确认对话框以及加载效果示例代码
2014/02/13 Javascript
Javascript的严格模式strict mode详细介绍
2014/06/06 Javascript
我的Node.js学习之路(一)
2014/07/06 Javascript
jQuery的css() 方法使用指南
2015/05/03 Javascript
轻松掌握JavaScript单例模式
2016/08/25 Javascript
详谈js中window.location.search的用法和作用
2017/02/13 Javascript
Nodejs中Express 常用中间件 body-parser 实现解析
2017/05/22 NodeJs
vue轮播图插件vue-awesome-swiper的使用代码实例
2017/07/10 Javascript
深入理解vue $refs的基本用法
2017/07/13 Javascript
js实现网页的两个input标签内的数值加减(示例代码)
2017/08/15 Javascript
详解js几个绕不开的事件兼容写法
2017/08/30 Javascript
微信小程序wx.request的简单封装
2019/11/13 Javascript
通过实例解析javascript Date对象属性及方法
2020/11/04 Javascript
javascript实现数字时钟效果
2021/02/06 Javascript
使用Matplotlib绘制不同颜色的带箭头的线实例
2020/04/17 Python
python实现与redis交互操作详解
2020/04/21 Python
美国领先的户外服装与装备用品店:Moosejaw
2016/08/25 全球购物
高三自我鉴定范文
2013/10/19 职场文书
自我反省检讨书
2014/01/23 职场文书
四风问题自查报告剖析材料
2014/02/08 职场文书
教师自我反思材料
2014/02/14 职场文书
学习群众路线的心得体会
2014/11/05 职场文书
2014年政协工作总结
2014/12/09 职场文书
青少年法制教育心得体会
2016/01/14 职场文书
护士心得体会范文
2016/01/25 职场文书
简单总结SpringMVC拦截器的使用方法
2021/06/28 Java/Android
pandas求平均数和中位数的方法实例
2021/08/04 Python