前言
大家好,我是林三心,用最通俗易懂的话讲最难的知识点是我的座右铭,基础是进阶的前提是我的初心。
检测网速
想要在Web端检测网速,其实很简单,有一个全局的对象——navigation,我们来看看它的身上都有哪些东西:
图片
属性 | 描述 | 类型 |
downlink | 有效带宽估算(单位:兆比特/秒) | number |
effectiveType | effectiveType | slow-2g/2g/3g/4g |
rtt | 当前连接下评估的往返时延 | number |
saveData | 用户代理是否设置了减少数据使用的选项 | boolean |
useNetwork
我们可以自定义一个hook,用来获取网页当前的网络状态~需要具备以下要素:
1、返回的数据所需的ts类、监听网络变化的enum
2、获取网络状态
3、监听网络变化,并实时更新最新的网络状态
第一步:所需的ts类型
说说NetworkState的各个参数:
- since:记录当时检测的时间
- oline:记录是否有网络
- rtt:记录时延
- downlink:记录带宽
- saveData:记录用户代理是否设置了减少数据使用
- effectiveType:网络连接类型
// hook返回的值
interface NetworkState {
since?: Date;
online?: boolean;
rtt?: number;
downlink?: number;
saveData?: boolean;
effectiveType?: string;
}
// 监听网络变化的事件名enum
enum NetworkEventType {
ONLINE = 'online',
OFFLINE = 'offline',
CHANGE = 'change',
}
第二步:获取网络状态
function getConnection() {
const nav = navigator as any;
if (typeof nav !== 'object') return null;
return nav.connection || nav.mozConnection || nav.webkitConnection;
}
function getConnectionProperty(): NetworkState {
const c = getConnection();
if (!c) return {};
return {
rtt: c.rtt,
saveData: c.saveData,
downlink: c.downlink,
effectiveType: c.effectiveType,
};
}
第三步:实时更新网络状态
unction useNetwork(): NetworkState {
const [state, setState] = useState(() => {
return {
since: undefined,
online: navigator?.onLine,
...getConnectionProperty(),
};
});
useEffect(() => {
const onOnline = () => {
setState((prevState) => ({
...prevState,
online: true,
since: new Date(),
}));
};
const onOffline = () => {
setState((prevState) => ({
...prevState,
online: false,
since: new Date(),
}));
};
const onConnectionChange = () => {
setState((prevState) => ({
...prevState,
...getConnectionProperty(),
}));
};
window.addEventListener(NetworkEventType.ONLINE, onOnline);
window.addEventListener(NetworkEventType.OFFLINE, onOffline);
const connection = getConnection();
connection?.addEventListener(NetworkEventType.CHANGE, onConnectionChange);
return () => {
window.removeEventListener(NetworkEventType.ONLINE, onOnline);
window.removeEventListener(NetworkEventType.OFFLINE, onOffline);
connection?.removeEventListener(NetworkEventType.CHANGE, onConnectionChange);
};
}, []);
return state;
}
完整代码
import { useEffect, useState } from 'react';
export interface NetworkState {
since?: Date;
online?: boolean;
rtt?: number;
downlink?: number;
saveData?: boolean;
effectiveType?: string;
}
enum NetworkEventType {
ONLINE = 'online',
OFFLINE = 'offline',
CHANGE = 'change',
}
function getConnection() {
const nav = navigator as any;
if (typeof nav !== 'object') return null;
return nav.connection || nav.mozConnection || nav.webkitConnection;
}
function getConnectionProperty(): NetworkState {
const c = getConnection();
if (!c) return {};
return {
rtt: c.rtt,
saveData: c.saveData,
downlink: c.downlink,
effectiveType: c.effectiveType,
};
}
function useNetwork(): NetworkState {
const [state, setState] = useState(() => {
return {
since: undefined,
online: navigator?.onLine,
...getConnectionProperty(),
};
});
useEffect(() => {
const onOnline = () => {
setState((prevState) => ({
...prevState,
online: true,
since: new Date(),
}));
};
const onOffline = () => {
setState((prevState) => ({
...prevState,
online: false,
since: new Date(),
}));
};
const onConnectionChange = () => {
setState((prevState) => ({
...prevState,
...getConnectionProperty(),
}));
};
window.addEventListener(NetworkEventType.ONLINE, onOnline);
window.addEventListener(NetworkEventType.OFFLINE, onOffline);
const connection = getConnection();
connection?.addEventListener(NetworkEventType.CHANGE, onConnectionChange);
return () => {
window.removeEventListener(NetworkEventType.ONLINE, onOnline);
window.removeEventListener(NetworkEventType.OFFLINE, onOffline);
connection?.removeEventListener(NetworkEventType.CHANGE, onConnectionChange);
};
}, []);
return state;
}
export default useNetwork;