如何用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 相关文章推荐
浅析offsetLeft,Left,clientLeft之间的区别
Nov 30 Javascript
javascript中的取反再取反~~没有意义
Apr 06 Javascript
微信JS接口汇总及使用详解
Jan 09 Javascript
在JavaScript中处理数组之reverse()方法的使用
Jun 09 Javascript
基于bootstrap实现广告轮播带图片和文字效果
Jul 22 Javascript
jQuery简单倒计时效果完整示例
Sep 20 Javascript
基于Node.js的WebSocket通信实现
Mar 11 Javascript
详解webpack 打包文件体积过大解决方案(code splitting)
Apr 10 Javascript
深入理解Node内建模块和对象
Mar 12 Javascript
Angular value与ngValue区别详解
Nov 27 Javascript
arcgis.js控制地图地体的显示范围超出区域自动弹回(实现思路)
Jan 28 Javascript
vue组件冲突之引用另一个组件出现组件不显示的问题
Apr 13 Vue.js
浅谈JS的二进制家族
如何使用vue3打造一个物料库
Ajax常用封装库——Axios的使用
May 08 #Javascript
微信小程序用户授权最佳实践指南
vue完美实现el-table列宽自适应
详解JS WebSocket断开原因和心跳机制
May 07 #Javascript
如何用threejs实现实时多边形折射
You might like
从C/C++迁移到PHP——判断字符类型的函数
2006/10/09 PHP
实用的简单PHP分页集合包括使用方法
2013/10/21 PHP
php遍历目录方法小结
2015/03/10 PHP
php文件操作相关类实例
2015/06/18 PHP
php 判断过去离现在几年的函数(实例代码)
2016/11/15 PHP
laravel框架路由分组,中间件,命名空间,子域名,路由前缀实例分析
2020/02/18 PHP
javascript实现的动态文字变换
2007/07/28 Javascript
JS遮罩层效果 兼容ie firefox jQuery遮罩层
2010/07/26 Javascript
$.format,jquery.format 使用说明
2011/07/13 Javascript
window.parent与window.openner区别介绍
2012/04/12 Javascript
jQuery中delegate()方法用法实例
2015/01/19 Javascript
JS实现支持多选的遍历下拉列表代码
2015/08/20 Javascript
Js制作点击输入框时默认文字消失的效果
2015/09/05 Javascript
编写高质量JavaScript代码的基本要点
2016/03/02 Javascript
浅析Bootstrap表格的使用
2016/06/23 Javascript
jquery实现瀑布流效果 jquery下拉加载新数据
2016/12/12 Javascript
Vue数据驱动模拟实现4
2017/01/12 Javascript
基于JavaScript实现数码时钟效果
2020/03/30 Javascript
微信小程序template模板实例详解
2017/10/27 Javascript
详解JavaScript中的坐标和距离
2019/05/27 Javascript
js笔试题-接收get请求参数
2019/06/15 Javascript
[01:00:04]DOTA2上海特级锦标赛B组小组赛#1 Alliance VS Spirit第二局
2016/02/26 DOTA
[03:06]3分钟带你回顾DOTA2完美盛典&完美大师赛
2017/12/06 DOTA
python实现根据用户输入从电影网站获取影片信息的方法
2015/04/07 Python
Python学习小技巧之利用字典的默认行为
2017/05/20 Python
Python不使用int()函数把字符串转换为数字的方法
2018/07/09 Python
python pygame实现方向键控制小球
2019/05/17 Python
Python绘制热力图示例
2019/09/27 Python
python pprint模块中print()和pprint()两者的区别
2020/02/10 Python
在脚本中单独使用django的ORM模型详解
2020/04/01 Python
Python基于unittest实现测试用例执行
2020/11/25 Python
Amara美国站:英国高端家居礼品网站,世界各地的奢侈家具品牌
2017/07/26 全球购物
英国知名小木屋定制网站:Tiger Sheds
2020/03/06 全球购物
简历的自我评价范文
2014/02/04 职场文书
班班通校本培训方案
2014/03/12 职场文书
严以律己专题学习研讨会发言材料
2015/11/09 职场文书