如何用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 相关文章推荐
Bookmarklet实现启动jQuery(模仿 云输入法)
Sep 15 Javascript
js使用数组判断提交数据是否存在相同数据
Nov 27 Javascript
display和visibility的区别示例介绍
Feb 26 Javascript
JavaScript中字符串拼接的基本方法
Jul 07 Javascript
jQuery简单实现input文本框内灰色提示文本效果的方法
Dec 02 Javascript
AngularJs 60分钟入门基础教程
Apr 03 Javascript
js将滚动条滚动到指定位置的简单实现方法
Jun 25 Javascript
利用PM2部署node.js项目的方法教程
May 10 Javascript
BetterScroll 在移动端滚动场景的应用
Sep 18 Javascript
微信小程序switch组件使用详解
Jan 31 Javascript
node.js的Express服务器基本使用教程
Jan 09 Javascript
《javascript设计模式》学习笔记四:Javascript面向对象程序设计链式调用实例分析
Apr 07 Javascript
浅谈JS的二进制家族
如何使用vue3打造一个物料库
Ajax常用封装库——Axios的使用
May 08 #Javascript
微信小程序用户授权最佳实践指南
vue完美实现el-table列宽自适应
详解JS WebSocket断开原因和心跳机制
May 07 #Javascript
如何用threejs实现实时多边形折射
You might like
功能强大的php文件上传类
2016/08/29 PHP
PHP实现上一篇下一篇的方法实例总结
2016/09/22 PHP
PHP共享内存使用与信号控制实例分析
2018/05/09 PHP
laravel 解决Validator使用中出现的问题
2019/10/25 PHP
用JavaScript隐藏控件的方法
2009/09/21 Javascript
JS隐藏参数post传值实例
2013/04/18 Javascript
javascript关于运动的各种问题经典总结
2015/04/27 Javascript
jquery遍历json对象集合详解
2016/05/18 Javascript
Javascript别踩白块儿(钢琴块儿)小游戏实现代码
2017/07/20 Javascript
Cropper.js 实现裁剪图片并上传(PC端)
2017/08/20 Javascript
Angular搜索 过滤 批量删除 添加 表单验证功能集锦(实例代码)
2017/10/25 Javascript
详解JS数值Number类型
2018/02/07 Javascript
JavaScript实现无限级递归树的示例代码
2019/03/29 Javascript
js实现div色块碰撞
2020/01/16 Javascript
nuxt 实现在其它js文件中使用store的方式
2020/11/05 Javascript
详解vue 组件注册
2020/11/20 Vue.js
[56:00]2018DOTA2亚洲邀请赛 4.6 淘汰赛 VP vs TNC 第二场
2018/04/10 DOTA
python实现将英文单词表示的数字转换成阿拉伯数字的方法
2015/07/02 Python
python爬虫面试宝典(常见问题)
2018/03/02 Python
python入门教程 python入门神图一张
2018/03/05 Python
Python enumerate函数功能与用法示例
2019/03/01 Python
详解js文件通过python访问数据库方法
2019/03/03 Python
在Python中COM口的调用方法
2019/07/03 Python
Python实现的统计文章单词次数功能示例
2019/07/08 Python
python之PyQt按钮右键菜单功能的实现代码
2019/08/17 Python
英国在线药房和在线医生:LloydsPharmacy
2019/10/21 全球购物
英国鞋网:Rubber Sole
2020/03/03 全球购物
资料员岗位职责
2013/11/17 职场文书
运动会解说词50字
2014/01/18 职场文书
少先队学雷锋活动月总结
2014/03/09 职场文书
如何写自我鉴定
2014/03/19 职场文书
美术专业自荐信
2014/07/07 职场文书
单位在职证明书
2014/09/11 职场文书
恋恋笔记本观后感
2015/06/16 职场文书
MySQL分区以及建索引的方法总结
2022/04/13 MySQL
SQL Server使用T-SQL语句批处理
2022/05/20 SQL Server