@ichaingo/web-socket
v1.4.85
Published
基于WebSocket的单例模式连接库,提供稳定可靠的WebSocket连接管理功能和React Hooks。
Readme
@ichaingo/socket
基于WebSocket的单例模式连接库,提供稳定可靠的WebSocket连接管理功能和React Hooks。
特性
- 🔄 单例模式: 确保全局只有一个WebSocket连接实例
- 🔁 自动重连: 连接断开时自动尝试重连,支持配置重连次数和间隔
- 💓 心跳检测: 定期发送心跳包保持连接活跃
- 📡 事件驱动: 支持多种事件监听(连接、消息、错误、状态变化等)
- 🛡️ 错误处理: 完善的错误处理和状态管理
- 📝 TypeScript: 完整的TypeScript类型支持
- 🐛 调试模式: 支持调试日志输出
- ⚛️ React Hooks: 提供便捷的React Hooks用于组件集成
安装
npm install @ichaingo/socket
# 或
pnpm add @ichaingo/socket
# 或
yarn add @ichaingo/socket快速开始
基本使用
import SocketConnection, { ConnectionStatus } from '@ichaingo/socket';
// 创建连接实例
const socket = SocketConnection.getInstance({
url: 'ws://localhost:8080',
debug: true
});
// 连接WebSocket
await socket.connect();
// 发送消息
socket.send('Hello WebSocket!');
socket.sendJSON({ type: 'message', content: 'Hello!' });
// 监听消息
socket.on('message', (data) => {
console.log('收到消息:', data);
});
// 监听连接状态变化
socket.on('statusChange', (status) => {
console.log('连接状态:', status);
});React Hooks 使用
useSocket Hook
import React from 'react';
import { useSocket } from '@ichaingo/socket';
function ChatComponent() {
const socket = useSocket({
url: 'ws://localhost:8080',
debug: true,
autoConnect: true
});
const [messages, setMessages] = useState<string[]>([]);
useEffect(() => {
socket.on('message', (data) => {
if (typeof data === 'string') {
setMessages(prev => [...prev, data]);
}
});
return () => {
socket.off('message');
};
}, [socket]);
const sendMessage = (message: string) => {
socket.send(message);
};
return (
<div>
<div>连接状态: {socket.status}</div>
<div>是否已连接: {socket.isConnected ? '是' : '否'}</div>
{/* 你的UI组件 */}
</div>
);
}useSocketMessage Hook
专门用于监听特定类型消息的简化Hook:
import React from 'react';
import { useSocketMessage } from '@ichaingo/socket';
interface ChatMessage {
user: string;
content: string;
timestamp: number;
}
function ChatComponent() {
const [messages, setMessages] = useState<ChatMessage[]>([]);
const socket = useSocketMessage<ChatMessage>({
url: 'ws://localhost:8080/chat',
debug: true,
autoConnect: true
}, (message) => {
setMessages(prev => [...prev, message]);
});
const sendMessage = (user: string, content: string) => {
socket.sendJSON({
user,
content,
timestamp: Date.now()
});
};
return (
<div>
<div>连接状态: {socket.status}</div>
{/* 你的UI组件 */}
</div>
);
}useSocketStatus Hook
专门用于监听连接状态的简化Hook:
import React from 'react';
import { useSocketStatus } from '@ichaingo/socket';
function StatusIndicator() {
const status = useSocketStatus({
url: 'ws://localhost:8080',
debug: true,
autoConnect: true
});
return (
<div>
<div>状态: {status.status}</div>
<div>是否已连接: {status.isConnected ? '是' : '否'}</div>
<div>是否正在连接: {status.isConnecting ? '是' : '否'}</div>
<div>是否正在重连: {status.isReconnecting ? '是' : '否'}</div>
<div>是否已断开: {status.isDisconnected ? '是' : '否'}</div>
<div>是否有错误: {status.hasError ? '是' : '否'}</div>
</div>
);
}API 参考
SocketConnection
静态方法
getInstance(config?: WebSocketConfig): SocketConnection- 获取单例实例
实例方法
connect(): Promise<void>- 连接WebSocketdisconnect(): void- 断开连接send(data: string | ArrayBuffer | Blob): boolean- 发送消息sendJSON(data: any): boolean- 发送JSON消息on<K extends keyof WebSocketEvents>(event: K, listener: WebSocketEvents[K]): void- 添加事件监听器off<K extends keyof WebSocketEvents>(event: K): void- 移除事件监听器getStatus(): ConnectionStatus- 获取连接状态isConnected(): boolean- 检查是否已连接destroy(): void- 销毁实例
React Hooks
useSocket
function useSocket(config: UseSocketConfig): UseSocketReturn参数:
config: WebSocket配置选项,继承自WebSocketConfig并添加了React相关选项
返回值:
status: 当前连接状态isConnected: 是否已连接connect: 连接方法disconnect: 断开连接方法send: 发送消息方法sendJSON: 发送JSON消息方法on: 添加事件监听器方法off: 移除事件监听器方法error: 当前错误状态reconnectAttempts: 重连次数reconnect: 手动重连方法
useSocketMessage
function useSocketMessage<T>(
config: UseSocketConfig,
messageHandler: (data: T) => void
): UseSocketReturn专门用于监听特定类型消息的简化Hook。
useSocketStatus
function useSocketStatus(config: UseSocketConfig): {
status: ConnectionStatus;
isConnected: boolean;
isConnecting: boolean;
isReconnecting: boolean;
isDisconnected: boolean;
hasError: boolean;
}专门用于监听连接状态的简化Hook。
类型定义
ConnectionStatus
enum ConnectionStatus {
CONNECTING = 'connecting',
CONNECTED = 'connected',
DISCONNECTED = 'disconnected',
RECONNECTING = 'reconnecting',
ERROR = 'error'
}WebSocketConfig
interface WebSocketConfig {
url: string; // WebSocket服务器URL
protocols?: string | string[]; // 子协议
reconnectInterval?: number; // 重连间隔(默认3000ms)
maxReconnectAttempts?: number; // 最大重连次数(默认5次)
heartbeatInterval?: number; // 心跳间隔(默认30000ms)
debug?: boolean; // 调试模式(默认false)
}UseSocketConfig
interface UseSocketConfig extends WebSocketConfig {
autoConnect?: boolean; // 是否自动连接(默认true)
reconnectOnMount?: boolean; // 组件挂载时是否重连(默认true)
}WebSocketEvents
interface WebSocketEvents {
open: () => void; // 连接打开
message: (data: string | ArrayBuffer | Blob) => void; // 收到消息
close: (event: CloseEvent) => void; // 连接关闭
error: (error: Event) => void; // 连接错误
statusChange: (status: ConnectionStatus) => void; // 状态变化
}使用示例
聊天应用
import React, { useState, useEffect } from 'react';
import { useSocket } from '@ichaingo/socket';
interface Message {
id: string;
user: string;
content: string;
timestamp: number;
}
function ChatApp() {
const [messages, setMessages] = useState<Message[]>([]);
const [inputMessage, setInputMessage] = useState('');
const [username, setUsername] = useState('');
const socket = useSocket({
url: 'ws://localhost:8080/chat',
debug: true,
autoConnect: true
});
useEffect(() => {
socket.on('message', (data) => {
if (typeof data === 'string') {
try {
const message = JSON.parse(data) as Message;
setMessages(prev => [...prev, message]);
} catch (err) {
console.error('Failed to parse message:', err);
}
}
});
return () => {
socket.off('message');
};
}, [socket]);
const sendMessage = () => {
if (inputMessage.trim() && username.trim()) {
const message: Message = {
id: Date.now().toString(),
user: username,
content: inputMessage,
timestamp: Date.now()
};
socket.sendJSON(message);
setInputMessage('');
}
};
return (
<div>
<div>连接状态: {socket.status}</div>
<div>
<input
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="用户名"
/>
<input
value={inputMessage}
onChange={(e) => setInputMessage(e.target.value)}
placeholder="输入消息"
onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
/>
<button onClick={sendMessage} disabled={!socket.isConnected}>
发送
</button>
</div>
<div>
{messages.map((message) => (
<div key={message.id}>
<strong>{message.user}:</strong> {message.content}
<small> ({new Date(message.timestamp).toLocaleTimeString()})</small>
</div>
))}
</div>
</div>
);
}实时通知系统
import React, { useState } from 'react';
import { useSocketMessage } from '@ichaingo/socket';
interface Notification {
id: string;
type: 'info' | 'warning' | 'error';
title: string;
content: string;
timestamp: number;
}
function NotificationSystem() {
const [notifications, setNotifications] = useState<Notification[]>([]);
const socket = useSocketMessage<Notification>({
url: 'ws://localhost:8080/notifications',
debug: true,
autoConnect: true
}, (notification) => {
setNotifications(prev => [notification, ...prev]);
});
const clearNotifications = () => {
setNotifications([]);
};
return (
<div>
<div>连接状态: {socket.status}</div>
<button onClick={clearNotifications}>清空通知</button>
<div>
{notifications.map((notification) => (
<div
key={notification.id}
style={{
padding: '10px',
margin: '5px 0',
border: '1px solid #ccc',
borderRadius: '4px',
backgroundColor: notification.type === 'error' ? '#ffebee' :
notification.type === 'warning' ? '#fff3e0' : '#e3f2fd'
}}
>
<strong>{notification.title}</strong>
<div>{notification.content}</div>
<small>{new Date(notification.timestamp).toLocaleString()}</small>
</div>
))}
</div>
</div>
);
}构建
nx build socket测试
nx test socket许可证
MIT
