通過JS獲取你當(dāng)前的網(wǎng)絡(luò)狀況?建議大家學(xué)一學(xué)
前言
大家好,我是林三心,用最通俗易懂的話講最難的知識點是我的座右銘,基礎(chǔ)是進階的前提是我的初心。
檢測網(wǎng)速
想要在Web端檢測網(wǎng)速,其實很簡單,有一個全局的對象——navigation,我們來看看它的身上都有哪些東西:
圖片
屬性 | 描述 | 類型 |
downlink | 有效帶寬估算(單位:兆比特/秒) | number |
effectiveType | effectiveType | slow-2g/2g/3g/4g |
rtt | 當(dāng)前連接下評估的往返時延 | number |
saveData | 用戶代理是否設(shè)置了減少數(shù)據(jù)使用的選項 | boolean |
useNetwork
我們可以自定義一個hook,用來獲取網(wǎng)頁當(dāng)前的網(wǎng)絡(luò)狀態(tài)~需要具備以下要素:
1、返回的數(shù)據(jù)所需的ts類、監(jiān)聽網(wǎng)絡(luò)變化的enum
2、獲取網(wǎng)絡(luò)狀態(tài)
3、監(jiān)聽網(wǎng)絡(luò)變化,并實時更新最新的網(wǎng)絡(luò)狀態(tài)
第一步:所需的ts類型
說說NetworkState的各個參數(shù):
- since:記錄當(dāng)時檢測的時間
- oline:記錄是否有網(wǎng)絡(luò)
- rtt:記錄時延
- downlink:記錄帶寬
- saveData:記錄用戶代理是否設(shè)置了減少數(shù)據(jù)使用
- effectiveType:網(wǎng)絡(luò)連接類型
// hook返回的值
interface NetworkState {
since?: Date;
online?: boolean;
rtt?: number;
downlink?: number;
saveData?: boolean;
effectiveType?: string;
}
// 監(jiān)聽網(wǎng)絡(luò)變化的事件名enum
enum NetworkEventType {
ONLINE = 'online',
OFFLINE = 'offline',
CHANGE = 'change',
}
第二步:獲取網(wǎng)絡(luò)狀態(tài)
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,
};
}
第三步:實時更新網(wǎng)絡(luò)狀態(tài)
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;