網頁開發中存在需要獲取用戶是否在線的場景及用戶網絡狀態,瀏覽器提了navigator.onLine和navigator.connection可以實現這一需求。
獲取在線狀態
if (navigator.onLine) {console.log("online");
} else {console.log("offline");
}
監聽網絡狀態變更事件
window.addEventListener("offline", (e) => {console.log("offline");
});window.addEventListener("online", (e) => {console.log("online");
});
通過 NetworkInformation API 獲取更多網絡相關信息
NetworkInformation API?中提供了更多網絡狀態相關的信息,如最大下行速度、網絡連接類型等。
function getConnection() {const nav = navigator as any;if (!isObject(nav)) return null;return nav.connection || nav.mozConnection || nav.webkitConnection;
}function getConnectionProperty(): NetworkState {const c = getConnection();if (!c) return {};return {rtt: c.rtt,type: c.type,saveData: c.saveData,downlink: c.downlink,downlinkMax: c.downlinkMax,effectiveType: c.effectiveType,};
}
屬性 | 描述 | 類型 |
---|---|---|
rtt | 當前連接下評估的往返時延 | number |
type | 設備使用與所述網絡進行通信的連接的類型 | bluetooth ?|?cellular ?|?ethernet ?|?none ?|?wifi ?|?wimax ?|?other ?|?unknown |
downlink | 有效帶寬估算(單位:兆比特/秒) | number |
downlinkMax | 最大下行速度(單位:兆比特/秒) | number |
saveData | 用戶代理是否設置了減少數據使用的選項 | boolean |
effectiveType | 網絡連接的類型 | slow-2g ?|?2g ?|?3g ?|?4g |
更多信息參考:MDN NetworkInformation
封裝成一個 useNetwork 自定義 Hook
以下代碼是 ahooks 中的 useNetwork 自定義 Hook 實現方式,其核心原理是通過以上的navigator.onLine和navigator.connection中提供的?API
?進行分裝的。
其他的自定義?Hooks
?也有類似實現的封裝。
import { useEffect, useState } from 'react';
import { isObject } from '../utils';export interface NetworkState {since?: Date;online?: boolean;rtt?: number;type?: string;downlink?: number;saveData?: boolean;downlinkMax?: number;effectiveType?: string;
}enum NetworkEventType {ONLINE = 'online',OFFLINE = 'offline',CHANGE = 'change',
}function getConnection() {const nav = navigator as any;if (!isObject(nav)) return null;return nav.connection || nav.mozConnection || nav.webkitConnection;
}function getConnectionProperty(): NetworkState {const c = getConnection();if (!c) return {};return {rtt: c.rtt,type: c.type,saveData: c.saveData,downlink: c.downlink,downlinkMax: c.downlinkMax,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;
useNetwork 自定義 Hook 使用方式
import React from 'react';
import { useNetwork } from 'ahooks';export default () => {const networkState = useNetwork();return (<div><div>Network information: </div><pre>{JSON.stringify(networkState, null, 2)}</pre></div>);
};