first commit
This commit is contained in:
159
src/services/networkService.ts
Normal file
159
src/services/networkService.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
export interface NetworkStatus {
|
||||
isOnline: boolean;
|
||||
lastOnlineTime?: Date;
|
||||
lastOfflineTime?: Date;
|
||||
lastCheck: Date;
|
||||
}
|
||||
|
||||
export type NetworkStatusCallback = (status: NetworkStatus) => void;
|
||||
|
||||
export class NetworkService {
|
||||
private static instance: NetworkService;
|
||||
private status: NetworkStatus;
|
||||
private callbacks: Set<NetworkStatusCallback> = new Set();
|
||||
private checkInterval?: NodeJS.Timeout;
|
||||
|
||||
private constructor() {
|
||||
const now = new Date();
|
||||
this.status = {
|
||||
isOnline: navigator.onLine,
|
||||
lastOnlineTime: navigator.onLine ? now : undefined,
|
||||
lastOfflineTime: !navigator.onLine ? now : undefined,
|
||||
lastCheck: now
|
||||
};
|
||||
|
||||
this.initializeListeners();
|
||||
this.startPeriodicCheck();
|
||||
}
|
||||
|
||||
public static getInstance(): NetworkService {
|
||||
if (!NetworkService.instance) {
|
||||
NetworkService.instance = new NetworkService();
|
||||
}
|
||||
return NetworkService.instance;
|
||||
}
|
||||
|
||||
private initializeListeners(): void {
|
||||
window.addEventListener('online', this.handleOnline.bind(this));
|
||||
window.addEventListener('offline', this.handleOffline.bind(this));
|
||||
}
|
||||
|
||||
private handleOnline(): void {
|
||||
console.log('网络连接已恢复');
|
||||
this.updateStatus(true);
|
||||
}
|
||||
|
||||
private handleOffline(): void {
|
||||
console.log('网络连接已断开');
|
||||
this.updateStatus(false);
|
||||
}
|
||||
|
||||
private updateStatus(isOnline: boolean): void {
|
||||
const now = new Date();
|
||||
this.status = {
|
||||
...this.status,
|
||||
isOnline,
|
||||
lastOnlineTime: isOnline ? now : this.status.lastOnlineTime,
|
||||
lastOfflineTime: !isOnline ? now : this.status.lastOfflineTime,
|
||||
lastCheck: now
|
||||
};
|
||||
|
||||
// 通知所有监听器
|
||||
this.callbacks.forEach(callback => {
|
||||
try {
|
||||
callback(this.status);
|
||||
} catch (error) {
|
||||
console.error('网络状态回调执行错误:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private startPeriodicCheck(): void {
|
||||
// 每30秒检查一次网络连接
|
||||
this.checkInterval = setInterval(() => {
|
||||
this.checkNetworkConnectivity();
|
||||
}, 30000);
|
||||
}
|
||||
|
||||
private async checkNetworkConnectivity(): Promise<void> {
|
||||
try {
|
||||
// 使用浏览器的在线状态作为主要判断依据
|
||||
const browserOnline = navigator.onLine;
|
||||
|
||||
if (!browserOnline) {
|
||||
if (this.status.isOnline) {
|
||||
console.log('浏览器检测到网络断开');
|
||||
this.updateStatus(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果浏览器认为在线,直接信任浏览器的判断
|
||||
// 避免额外的网络请求导致不必要的错误日志
|
||||
if (browserOnline !== this.status.isOnline) {
|
||||
this.updateStatus(browserOnline);
|
||||
} else {
|
||||
// 即使状态没变,也要更新检查时间
|
||||
this.status.lastCheck = new Date();
|
||||
}
|
||||
} catch (error) {
|
||||
// 检测过程出错,保持当前状态
|
||||
console.warn('网络状态检测出错:', error);
|
||||
}
|
||||
}
|
||||
|
||||
public getStatus(): NetworkStatus {
|
||||
return { ...this.status };
|
||||
}
|
||||
|
||||
public isOnline(): boolean {
|
||||
return this.status.isOnline;
|
||||
}
|
||||
|
||||
public subscribe(callback: NetworkStatusCallback): () => void {
|
||||
this.callbacks.add(callback);
|
||||
|
||||
// 立即调用一次回调,提供当前状态
|
||||
callback(this.status);
|
||||
|
||||
// 返回取消订阅函数
|
||||
return () => {
|
||||
this.callbacks.delete(callback);
|
||||
};
|
||||
}
|
||||
|
||||
public async waitForOnline(timeout: number = 30000): Promise<boolean> {
|
||||
if (this.status.isOnline) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
unsubscribe();
|
||||
resolve(false);
|
||||
}, timeout);
|
||||
|
||||
const unsubscribe = this.subscribe((status) => {
|
||||
if (status.isOnline) {
|
||||
clearTimeout(timeoutId);
|
||||
unsubscribe();
|
||||
resolve(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
window.removeEventListener('online', this.handleOnline.bind(this));
|
||||
window.removeEventListener('offline', this.handleOffline.bind(this));
|
||||
|
||||
if (this.checkInterval) {
|
||||
clearInterval(this.checkInterval);
|
||||
}
|
||||
|
||||
this.callbacks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
export const networkService = NetworkService.getInstance();
|
||||
export default NetworkService;
|
||||
Reference in New Issue
Block a user