网络监控

一. 浏览器api

  1. 监控网络连接状态

使用HTML5新增的offlineonlnie事件

1
2
window.addEventListener('offline', '<fn>') //离线状态下执行
window.addEventListener('online', '<fn>') //在线状态下执行
  1. 监控网络速度

使用navigator.connection可以拿到网络的一些信息

1
2
3
4
5
6
7
{
effectiveType: '4g',
rtt: 200,
downlink: 10,
saveData: false,
onchange: ƒ
}

其中:

  • effectiveType: 网络类型 比如: 4g、3g、2g等
  • rtt: 估算的往返时间
  • downlink: 网络下行速度
  • saveDate: 打开/请求数据保护模式
  • onchange: 设置navigator.connection改变之后的回调

使用方法:

1
2
3
4
5
6
7
8
9
const connection =
navigator.connection ||
navigator.mozConnection ||
navigator.webkitConnection

const fn = function () {
// do something
}
connection.onchange = fn

在项目中使用上面的方法之后,测试发现效果并不是很好。比如:

  • 电脑断开网络连接没有触发离线(offline)事件(电脑端谷歌浏览器(版本 104.0.5112.102(正式版本)))
  • 通过软件控制电脑网速不会触发navigator.connection的onchange

二.请求轮询

使用创建img标签加载图片,通过判断加载成功与失败、加载时长来判断网络状态

具体实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
const networkState = ref('off')
const networkOnCallback = []
const networkOffCallback = []

let timer = null
let imgDom = null
let imgLoadTime = 8
let waitTime = ref(2000)
const onNetworkState = function () {
//清空定时器和dom,防止内存泄露
clearTimeout(timer)
imgDom = null
timer = setTimeout(function () {
//请求发起时间
const imgLoadTimeStart = new Date().getTime()
imgDom = document.createElement('img')
imgDom.setAttribute(
'src',
`/logo-lg.png?date=${new Date().getTime()}`
)
imgDom.onload = () => {
//加载成功时长
const imgLoadSuccessTime = new Date().getTime()
// 加载过程总时长
const loadTime = imgLoadSuccessTime - imgLoadTimeStart
// 加载时长超过10秒 提示网络差
if (loadTime > 10000) {
ElMessage(
{ message: '网络状态不佳', type: 'error' },
appContext
)
// 网络不佳,减少轮询间隔时长
if (waitTime.value > 2 * 1000) {
waitTime.value -= 500
}
} else {
//请求成功,增加轮询间隔时长
if (waitTime.value < 10 * 1000) {
waitTime.value += 200
}
}

//执行回调,防止多次执行
if (networkState.value === 'off') {
networkOnCallback.map(cb => {
cb && cb()
})
}

networkState.value = 'on'

//递归轮询
onNetworkState()
}
imgDom.onerror = err => {
// 执行断网回调
if (networkState.value === 'on') {
networkOffCallback.map(cb => {
cb && cb()
})
}
// 缩短轮询间隔时长
waitTime.value = 2000
networkState.value = 'off'
// 递归轮询
onNetworkState()
}
}, waitTime.value)
}
onNetworkState()

const removerCallback = function (type = 'on', callback) {
if (type === 'on') {
const onIndex = networkOnCallback.findIndex(cb => {
return cb === callback
})
onIndex >= 0 && networkOnCallback.splice(onIndex, 1)
} else {
const offIndex = networkOffCallback.findIndex(cb => {
return cb === callback
})
offIndex >= 0 && networkOffCallback.splice(offIndex, 1)
}
}

const addCallback = function (type = 'on', callback) {
if (type === 'on') {
networkOnCallback.push(callback)
} else {
networkOffCallback.push(callback)
}
}