通過JS獲取你當前的網絡狀況?建議大家學一學
前言
大家好,我是林三心,用最通俗易懂的話講最難的知識點是我的座右銘,基礎是進階的前提是我的初心。
檢測網速
想要在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;