完整注释版代码
/**
* WebSocket 消息接口
* 定义WebSocket通信的消息格式
* @template T 消息数据的类型,默认为any
*/
export interface WebSocketMessage<T = any> {
/** 消息类型,用于区分不同的业务场景 */
type: string;
/** 消息数据,泛型T允许灵活定义数据结构 */
data: T;
/** 消息时间戳,用于记录消息创建时间 */
timestamp: number;
}
/**
* WebSocket 状态枚举
* 对应WebSocket的readyState属性值
*/
export enum WebSocketStatus {
/** 连接中 - WebSocket正在建立连接 */
CONNECTING = 0,
/** 打开/已连接 - 连接已建立,可以通信 */
OPEN = 1,
/** 关闭中/断开中 - 连接正在关闭 */
CLOSING = 2,
/** 已关闭/已断开 - 连接已关闭或未能建立 */
CLOSED = 3
}
/**
* 托管 WebSocket 配置选项接口
* 用于配置ManagedWebSocket的行为
*/
export interface ManagedWebSocketOptions {
/** WebSocket连接地址,如:ws://localhost:8080 */
url: string;
/** 可选的WebSocket子协议 */
protocols?: string | string[];
/** 是否自动重连,默认false */
autoReconnect?: boolean;
/** 重连间隔时间(毫秒),默认3000 */
reconnectInterval?: number;
/** 最大重连尝试次数,默认5次 */
maxReconnectAttempts?: number;
/** 心跳间隔时间(毫秒),不设置则不开启心跳 */
heartbeatInterval?: number;
/** 连接成功时的回调函数 */
onOpen?: (event: Event) => void;
/** 接收到消息时的回调函数 */
onMessage?: <T>(message: WebSocketMessage<T>) => void;
/** 发生错误时的回调函数 */
onError?: (event: Event) => void;
/** 连接关闭时的回调函数 */
onClose?: (event: CloseEvent) => void;
}
/**
* 托管 WebSocket 类
* 具备自动重连、心跳检测等管理功能的 WebSocket 封装
*
* 功能特性:
* - 自动重连机制(支持指数退避算法)
* - 心跳保活机制
* - 连接状态管理
* - 错误处理和恢复
* - 手动重连控制
*/
export class ManagedWebSocket {
/** WebSocket实例 */
private ws: WebSocket | null = null;
/** 当前重连尝试次数 */
private reconnectAttempts = 0;
/** 心跳定时器ID */
private heartbeatTimer: number | null = null;
/** 是否手动关闭的标志,手动关闭时不自动重连 */
private isManualClose = false;
/**
* 构造函数
* @param options 配置选项
*/
constructor(private options: ManagedWebSocketOptions) {
// 创建实例时立即建立连接
this.connect();
}
/**
* 建立WebSocket连接
* 创建WebSocket实例并设置事件处理器
*/
private connect(): void {
try {
// 创建WebSocket实例
this.ws = new WebSocket(this.options.url, this.options.protocols);
// 设置事件监听器
this.setupEventHandlers();
} catch (error) {
console.error('WebSocket connection failed:', error);
// 连接失败时尝试重连
this.handleReconnect();
}
}
/**
* 设置WebSocket事件处理器
* 处理连接打开、消息接收、错误和关闭事件
*/
private setupEventHandlers(): void {
if (!this.ws) return;
// 连接成功事件
this.ws.onopen = (event: Event) => {
console.log('WebSocket connected');
// 重置重连计数器
this.reconnectAttempts = 0;
// 启动心跳检测
this.startHeartbeat();
// 调用用户提供的onOpen回调
this.options.onOpen?.(event);
};
// 消息接收事件
this.ws.onmessage = (event: MessageEvent) => {
try {
// 解析JSON格式的消息
const message: WebSocketMessage = JSON.parse(event.data);
// 调用用户提供的onMessage回调
this.options.onMessage?.(message);
// 特殊处理:如果是心跳响应消息
if (message.type === 'pong') {
this.handlePong();
}
} catch (error) {
console.error('Failed to parse WebSocket message:', error);
}
};
// 错误事件
this.ws.onerror = (event: Event) => {
console.error('WebSocket error:', event);
// 调用用户提供的onError回调
this.options.onError?.(event);
};
// 连接关闭事件
this.ws.onclose = (event: CloseEvent) => {
console.log('WebSocket closed:', event.code, event.reason);
// 停止心跳检测
this.stopHeartbeat();
// 调用用户提供的onClose回调
this.options.onClose?.(event);
// 如果不是手动关闭且启用了自动重连,则尝试重连
if (!this.isManualClose && this.options.autoReconnect) {
this.handleReconnect();
}
};
}
/**
* 处理重连逻辑
* 使用指数退避算法避免频繁重连
*/
private handleReconnect(): void {
// 1. 检查是否超过最大重连次数
const maxAttempts = this.options.maxReconnectAttempts || 5;
if (this.reconnectAttempts >= maxAttempts) {
console.error('Max reconnection attempts reached');
return;
}
// 2. 计算重连间隔(指数退避算法)
const baseInterval = this.options.reconnectInterval || 3000;
// 重连间隔 = 基础间隔 × 1.5^重连次数,让重连间隔越来越长
const backoffInterval = baseInterval * Math.pow(1.5, this.reconnectAttempts);
console.log(`Attempting to reconnect in ${backoffInterval}ms (attempt ${this.reconnectAttempts + 1})`);
// 3. 设置定时器进行重连
setTimeout(() => {
this.reconnectAttempts++;
this.connect();
}, backoffInterval);
}
/**
* 启动心跳检测
* 定期发送ping消息检测连接是否存活
*/
private startHeartbeat(): void {
// 如果没有设置心跳间隔,则不启动心跳
if (!this.options.heartbeatInterval) return;
// 设置定时器,定期发送心跳
this.heartbeatTimer = window.setInterval(() => {
if (this.isConnected()) {
// 发送ping消息
this.send({
type: 'ping',
data: null,
timestamp: Date.now()
});
}
}, this.options.heartbeatInterval);
}
/**
* 停止心跳检测
* 清理心跳定时器
*/
private stopHeartbeat(): void {
if (this.heartbeatTimer) {
clearInterval(this.heartbeatTimer);
this.heartbeatTimer = null;
}
}
/**
* 处理心跳响应
* 接收到pong消息时的处理,可用于更新最后活跃时间
*/
private handlePong(): void {
// 这里可以记录最后收到pong的时间
// 用于检测连接是否真的存活,如果长时间没收到pong可以主动重连
// 当前实现为空,可根据需要扩展
}
/**
* 发送消息
* @param message 要发送的消息
* @returns 发送是否成功
*/
public send<T>(message: WebSocketMessage<T>): boolean {
// 检查连接状态
if (!this.isConnected()) {
console.error('WebSocket is not connected');
return false;
}
try {
// 将消息对象转换为JSON字符串并发送
this.ws!.send(JSON.stringify(message));
return true;
} catch (error) {
console.error('Failed to send WebSocket message:', error);
return false;
}
}
/**
* 主动关闭WebSocket连接
* @param code 关闭代码,默认1000(正常关闭)
* @param reason 关闭原因
*/
public close(code?: number, reason?: string): void {
// 设置手动关闭标志,避免自动重连
this.isManualClose = true;
// 停止心跳检测
this.stopHeartbeat();
// 关闭WebSocket连接
if (this.ws) {
this.ws.close(code || 1000, reason);
}
}
/**
* 检查连接是否处于打开状态
* @returns 是否已连接
*/
public isConnected(): boolean {
return this.ws?.readyState === WebSocketStatus.OPEN;
}
/**
* 获取当前WebSocket状态
* @returns WebSocket状态枚举值
*/
public getReadyState(): WebSocketStatus {
return this.ws?.readyState ?? WebSocketStatus.CLOSED;
}
/**
* 手动触发重连
* 用于网络恢复等场景下的主动重连
*/
public reconnect(): void {
// 重置手动关闭标志,允许重连
this.isManualClose = false;
// 重置重连计数器
this.reconnectAttempts = 0;
// 如果存在现有连接,先关闭
if (this.ws) {
this.ws.close();
}
// 建立新连接
this.connect();
}
}
详细分析讲解
1. 核心设计思想
这个 ManagedWebSocket 类是对原生 WebSocket 的增强封装,主要解决了以下问题:
-
连接稳定性:自动重连机制
-
连接健康度:心跳检测
-
状态管理:统一的状态枚举
-
错误恢复:完善的错误处理
2. 核心组件分析
2.1 消息格式 (WebSocketMessage)
typescript
interface WebSocketMessage<T = any> {
type: string; // 消息类型标识
data: T; // 消息内容(泛型)
timestamp: number; // 时间戳
}
作用:统一前后端通信的消息格式,便于类型检查和数据处理。
2.2 连接状态 (WebSocketStatus)
typescript
enum WebSocketStatus {
CONNECTING = 0, // 连接中
OPEN = 1, // 已连接
CLOSING = 2, // 关闭中
CLOSED = 3 // 已关闭
}
作用:使用枚举替代魔术数字,提高代码可读性。
2.3 配置选项 (ManagedWebSocketOptions)
提供灵活的配置,包括:
-
基础配置:URL、协议
-
重连配置:自动重连、重连策略
-
心跳配置:保活机制
-
事件回调:各种状态的回调函数
3. 关键技术点
3.1 自动重连机制
typescript
private handleReconnect(): void {
// 指数退避算法:重连间隔越来越长
const backoffInterval = interval * Math.pow(1.5, this.reconnectAttempts);
}
原理:使用指数退避算法避免频繁重连对服务器造成压力。
3.2 心跳检测
typescript
private startHeartbeat(): void {
this.heartbeatTimer = window.setInterval(() => {
if (this.isConnected()) {
this.send({ type: 'ping', data: null, timestamp: Date.now() });
}
}, this.options.heartbeatInterval);
}
作用:定期发送ping消息,检测连接是否真正可用。
3.3 手动关闭标识
typescript
private isManualClose = false;
作用:区分主动关闭和意外断开,只有意外断开才自动重连。
4. 使用示例
typescript
// 创建托管WebSocket实例
const ws = new ManagedWebSocket({
url: 'ws://localhost:8080',
autoReconnect: true,
reconnectInterval: 3000,
maxReconnectAttempts: 5,
heartbeatInterval: 30000,
onOpen: (event) => {
console.log('连接成功');
},
onMessage: (message) => {
console.log('收到消息:', message);
// 根据消息类型处理不同业务
switch (message.type) {
case 'chat':
console.log('聊天消息:', message.data);
break;
case 'notification':
console.log('通知:', message.data);
break;
}
},
onClose: (event) => {
console.log('连接关闭', event.code, event.reason);
}
});
// 发送消息
ws.send({
type: 'chat',
data: { text: 'Hello World' },
timestamp: Date.now()
});
// 检查连接状态
if (ws.isConnected()) {
console.log('连接正常');
}
// 手动重连
ws.reconnect();
// 主动关闭
ws.close(1000, '用户主动关闭');
5. 新手学习要点
5.1 TypeScript 特性
-
泛型:
WebSocketMessage<T>让消息数据可以是任意类型 -
接口:定义对象结构,提供类型安全
-
枚举:替代魔术数字,提高可读性
-
可选属性:
protocols?: string中的?表示该属性可选
5.2 设计模式
-
观察者模式:通过回调函数通知状态变化
-
策略模式:配置选项允许自定义行为
-
状态模式:通过状态枚举管理连接生命周期
5.3 错误处理
typescript
try {
// 可能出错的代码
} catch (error) {
// 错误处理
console.error('操作失败:', error);
// 恢复措施
this.handleReconnect();
}
6. 扩展建议
可以根据需要添加以下功能:
-
消息队列:连接断开时缓存未发送的消息
-
连接超时:设置连接建立超时时间
-
认证重连:支持带认证信息的重连
-
网络状态检测:结合navigator.onLine检测网络状态
这个封装类很好地展示了如何将一个基础API封装成生产可用的工具类,是学习TypeScript和网络编程的优秀示例!
结合这个 WebSocket 实例,我来为你详细讲解 class 和 interface 的区别和作用。
1. 基本概念对比
interface(接口)
typescript
// 接口:定义"应该有什么"
export interface WebSocketMessage<T = any> {
type: string; // 必须有 type
data: T; // 必须有 data
timestamp: number; // 必须有 timestamp
}
class(类)
typescript
// 类:定义"是什么" + "能做什么"
export class ManagedWebSocket {
private ws: WebSocket | null = null; // 属性
private reconnectAttempts = 0; // 属性
constructor(private options: ManagedWebSocketOptions) { // 构造函数
this.connect();
}
public send<T>(message: WebSocketMessage<T>): boolean { // 方法
// 具体实现...
}
}
2. 在实例中的具体作用分析
2.1 interface 的作用
定义数据结构(WebSocketMessage)
typescript
export interface WebSocketMessage<T = any> {
type: string;
data: T;
timestamp: number;
}
// 使用示例:类型约束
const chatMessage: WebSocketMessage<{ text: string }> = {
type: 'chat',
data: { text: 'Hello' }, // 这里必须是 { text: string } 类型
timestamp: Date.now()
};
const notificationMessage: WebSocketMessage<{ title: string }> = {
type: 'notification',
data: { title: 'Alert' }, // 这里必须是 { title: string } 类型
timestamp: Date.now()
};
作用:确保所有 WebSocket 消息都有统一的结构,便于序列化和解析。
定义配置契约(ManagedWebSocketOptions)
typescript
export interface ManagedWebSocketOptions {
url: string; // 必须的配置
protocols?: string | string[]; // 可选的配置
autoReconnect?: boolean;
// ... 其他配置
}
作用:明确告诉使用者创建 ManagedWebSocket 时需要提供哪些配置。
定义回调函数签名
typescript
onMessage?: <T>(message: WebSocketMessage<T>) => void;
作用:规定回调函数的参数类型,确保类型安全。
2.2 class 的作用
封装实现逻辑
typescript
export class ManagedWebSocket {
private ws: WebSocket | null = null; // 封装内部状态
private reconnectAttempts = 0; // 封装内部状态
private heartbeatTimer: number | null = null; // 封装内部状态
// 封装连接逻辑
private connect(): void {
this.ws = new WebSocket(this.options.url, this.options.protocols);
this.setupEventHandlers();
}
// 封装重连逻辑
private handleReconnect(): void {
// 复杂的重连算法实现...
}
}
提供公共 API
typescript
public send<T>(message: WebSocketMessage<T>): boolean {
// 对外提供发送消息的能力
}
public close(code?: number, reason?: string): void {
// 对外提供关闭连接的能力
}
public isConnected(): boolean {
// 对外提供状态查询能力
}
管理对象生命周期
typescript
constructor(private options: ManagedWebSocketOptions) {
this.connect(); // 创建时自动连接
}
public close(code?: number, reason?: string): void {
this.isManualClose = true;
this.stopHeartbeat();
if (this.ws) {
this.ws.close(code || 1000, reason);
}
}
3. 核心区别详解
3.1 编译结果不同
interface - 编译后消失
typescript
// TypeScript 源码
interface WebSocketMessage {
type: string;
data: any;
}
// 编译后的 JavaScript:什么都没有!
// interface 只在编译阶段用于类型检查
class - 编译后保留
typescript
// TypeScript 源码
class ManagedWebSocket {
private ws = null;
connect() { /* ... */ }
}
// 编译后的 JavaScript
class ManagedWebSocket {
constructor() {
this.ws = null;
}
connect() { /* ... */ }
}
3.2 实例化能力不同
interface - 不能实例化
typescript
const message = new WebSocketMessage(); // ❌ 错误!接口不能new
class - 可以实例化
typescript
const ws = new ManagedWebSocket({ url: 'ws://...' }); // ✅ 正确!
3.3 实现与声明的关系
interface 声明"有什么"
typescript
// 声明:一个可以连接的东西应该有 connect 方法
interface Connectable {
connect(): void;
isConnected(): boolean;
}
class 实现"怎么做"
typescript
// 实现:具体怎么连接
class ManagedWebSocket implements Connectable {
connect(): void {
// 具体的连接实现
this.ws = new WebSocket(this.options.url);
}
isConnected(): boolean {
// 具体的状态检查实现
return this.ws?.readyState === WebSocketStatus.OPEN;
}
}
4. 实际配合使用场景
4.1 类实现接口(契约编程)
typescript
// 定义契约
interface Reconnectable {
reconnect(): void;
maxReconnectAttempts: number;
}
// 类实现契约
export class ManagedWebSocket implements Reconnectable {
public maxReconnectAttempts: number;
public reconnect(): void {
this.isManualClose = false;
this.reconnectAttempts = 0;
if (this.ws) {
this.ws.close();
}
this.connect();
}
}
4.2 接口描述类实例的形状
typescript
// 接口描述类实例应该有的公共方法
export interface IManagedWebSocket {
send<T>(message: WebSocketMessage<T>): boolean;
close(code?: number, reason?: string): void;
isConnected(): boolean;
reconnect(): void;
}
// 类实现这个接口
export class ManagedWebSocket implements IManagedWebSocket {
// 必须实现接口中定义的所有方法
public send<T>(message: WebSocketMessage<T>): boolean {
// 实现...
}
public close(code?: number, reason?: string): void {
// 实现...
}
// ... 其他方法
}
4.3 依赖注入中的使用
typescript
// 定义服务接口
interface WebSocketService {
sendMessage<T>(type: string, data: T): boolean;
onMessage<T>(callback: (message: WebSocketMessage<T>) => void): void;
}
// 实现服务
class ManagedWebSocketService implements WebSocketService {
private ws: ManagedWebSocket;
constructor(options: ManagedWebSocketOptions) {
this.ws = new ManagedWebSocket(options);
}
sendMessage<T>(type: string, data: T): boolean {
return this.ws.send({
type,
data,
timestamp: Date.now()
});
}
onMessage<T>(callback: (message: WebSocketMessage<T>) => void): void {
this.ws.options.onMessage = callback;
}
}
5. 新手使用建议
什么时候用 interface?
-
定义数据模型:如 API 响应、消息格式
-
函数参数约束:确保传入的对象有特定属性
-
类公共 API 描述:定义类应该实现的方法
-
配置对象定义:如构造函数的配置选项
什么时候用 class?
-
需要实例化对象:要创建多个相似对象
-
封装复杂逻辑:有内部状态和复杂方法
-
需要继承:要扩展或重写现有功能
-
管理生命周期:如连接、资源清理等
实际开发中的模式
typescript
// 1. 先用 interface 设计
interface User {
id: number;
name: string;
email: string;
}
interface UserService {
getUser(id: number): Promise<User>;
updateUser(user: User): Promise<boolean>;
}
// 2. 再用 class 实现
class HttpUserService implements UserService {
private baseUrl: string;
constructor(baseUrl: string) {
this.baseUrl = baseUrl;
}
async getUser(id: number): Promise<User> {
const response = await fetch(`${this.baseUrl}/users/${id}`);
return response.json();
}
async updateUser(user: User): Promise<boolean> {
// 实现更新逻辑
return true;
}
}
6. 总结
| 特性 | interface | class |
|---|---|---|
| 作用 | 定义结构契约 | 创建具体实现 |
| 实例化 | ❌ 不能 | ✅ 能 |
| 编译后 | 消失 | 保留 |
| 包含实现 | ❌ 不能 | ✅ 能 |
| 访问修饰符 | ❌ 没有 | ✅ 有 |
| 继承 | 接口继承接口 | 类继承类 |
简单记忆:
-
interface = 蓝图/合同(规定应该有什么)
-
class = 房子/实现(具体建造和使用)
在这个 WebSocket 例子中:
-
interface用来定义消息格式和配置选项(数据层面) -
class用来实现具体的连接管理逻辑(行为层面)
两者配合使用,既能保证类型安全,又能提供完整的业务功能实现。
封闭好的类需要导出才能在组件中调用。让我详细解释这个机制。
1. 模块系统基础
1.1 导出(Export)
typescript
// managed-websocket.ts
export class ManagedWebSocket { // 使用 export 关键字
// ... 类实现
}
export interface WebSocketMessage {
// ... 接口定义
}
export enum WebSocketStatus {
// ... 枚举定义
}
1.2 导入(Import)
typescript
// 组件文件 component.ts
import {
ManagedWebSocket,
WebSocketMessage,
WebSocketStatus
} from './managed-websocket'; // 从文件路径导入
2. 为什么需要导出?
2.1 模块隔离
现代前端开发中,每个文件都是一个独立的模块:
typescript
// file-a.ts
class MyClass { } // 没有 export,只在当前文件可见
// file-b.ts
import { MyClass } from './file-a'; // ❌ 错误!MyClass 不可见
2.2 作用域保护
typescript
// utils.ts
// 内部使用的辅助函数,不需要导出
function formatDate(date: Date): string {
return date.toISOString();
}
// 对外提供的工具函数,需要导出
export function generateId(): string {
return Math.random().toString(36).substr(2, 9);
}
3. 不同的导出方式
3.1 命名导出(Named Exports)
typescript
// 方式1:直接导出
export class ManagedWebSocket { }
// 方式2:先定义后导出
class ManagedWebSocket { }
interface WebSocketMessage { }
enum WebSocketStatus { }
export { ManagedWebSocket, WebSocketMessage, WebSocketStatus };
// 方式3:重命名导出
export { ManagedWebSocket as WSManager };
3.2 默认导出(Default Export)
typescript
// 一个文件通常只有一个默认导出
export default class ManagedWebSocket {
// ...
}
// 或者
class ManagedWebSocket { }
export default ManagedWebSocket;
3.3 混合导出
typescript
export class ManagedWebSocket {
// 主要功能类
}
export interface WebSocketMessage {
// 辅助类型
}
// 工具函数作为默认导出
export default function createWebSocket(options: any) {
return new ManagedWebSocket(options);
}
4. 对应的导入方式
4.1 命名导入
typescript
import { ManagedWebSocket, WebSocketMessage } from './managed-websocket';
// 重命名导入
import { ManagedWebSocket as WS } from './managed-websocket';
4.2 默认导入
typescript
import ManagedWebSocket from './managed-websocket'; // 或者重命名 import WS from './managed-websocket';
4.3 全部导入
typescript
import * as WebSocketModule from './managed-websocket'; // 使用 const ws = new WebSocketModule.ManagedWebSocket(options);
5. 在实际项目中的使用
5.1 React 组件中的使用
typescript
// components/ChatComponent.tsx
import React, { useState, useEffect } from 'react';
import { ManagedWebSocket, WebSocketMessage } from '../utils/managed-websocket';
const ChatComponent: React.FC = () => {
const [websocket, setWebsocket] = useState<ManagedWebSocket | null>(null);
const [messages, setMessages] = useState<string[]>([]);
useEffect(() => {
// 创建 WebSocket 实例
const ws = new ManagedWebSocket({
url: 'ws://localhost:8080/chat',
autoReconnect: true,
onMessage: (message: WebSocketMessage) => {
setMessages(prev => [...prev, message.data]);
}
});
setWebsocket(ws);
// 清理函数
return () => {
ws.close();
};
}, []);
const sendMessage = (text: string) => {
if (websocket?.isConnected()) {
websocket.send({
type: 'chat',
data: text,
timestamp: Date.now()
});
}
};
return (
<div>
{/* 组件 JSX */}
</div>
);
};
export default ChatComponent; // 导出组件供其他文件使用
5.2 Vue 组件中的使用
typescript
<!-- components/ChatComponent.vue -->
<template>
<div>
<!-- 模板内容 -->
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, onUnmounted, ref } from 'vue';
import { ManagedWebSocket, WebSocketMessage } from '../utils/managed-websocket';
export default defineComponent({
name: 'ChatComponent',
setup() {
const websocket = ref<ManagedWebSocket | null>(null);
const messages = ref<string[]>([]);
onMounted(() => {
websocket.value = new ManagedWebSocket({
url: 'ws://localhost:8080/chat',
autoReconnect: true,
onMessage: (message: WebSocketMessage) => {
messages.value.push(message.data);
}
});
});
onUnmounted(() => {
websocket.value?.close();
});
const sendMessage = (text: string) => {
if (websocket.value?.isConnected()) {
websocket.value.send({
type: 'chat',
data: text,
timestamp: Date.now()
});
}
};
return {
messages,
sendMessage
};
}
});
</script>
5.3 Angular 服务中的使用
typescript
// services/websocket.service.ts
import { Injectable } from '@angular/core';
import { ManagedWebSocket, WebSocketMessage } from '../utils/managed-websocket';
@Injectable({
providedIn: 'root' // Angular 的导出方式
})
export class WebSocketService {
private websocket: ManagedWebSocket | null = null;
connect(url: string): void {
this.websocket = new ManagedWebSocket({
url,
autoReconnect: true,
onMessage: (message: WebSocketMessage) => {
this.handleMessage(message);
}
});
}
private handleMessage(message: WebSocketMessage): void {
// 处理消息
}
sendMessage(data: any): boolean {
return this.websocket?.send({
type: 'message',
data,
timestamp: Date.now()
}) ?? false;
}
disconnect(): void {
this.websocket?.close();
}
}
6. 导出最佳实践
6.1 按功能模块组织
typescript
// websocket/index.ts - 入口文件
export { ManagedWebSocket } from './managed-websocket';
export { WebSocketMessage } from './types';
export { WebSocketStatus } from './enums';
export { createWebSocket, closeAllConnections } from './utils';
// 使用时可以一次性导入
import { ManagedWebSocket, WebSocketMessage } from './websocket';
6.2 控制导出范围
typescript
// managed-websocket.ts
export class ManagedWebSocket { // 公共 API
public send() { } // 公共方法
public close() { } // 公共方法
private connect() { } // 私有方法,不需要导出
}
// 只导出用户需要使用的部分
export { ManagedWebSocket };
// 不导出内部使用的辅助函数和类
6.3 使用 Barrel Export
typescript
// utils/index.ts
export * from './websocket';
export * from './validation';
export * from './formatters';
// 组件中导入
import { ManagedWebSocket, validateEmail } from '../utils';
7. 常见错误和解决方案
7.1 忘记导出
typescript
// ❌ 错误:类没有导出
class ManagedWebSocket { }
// ✅ 正确:使用 export
export class ManagedWebSocket { }
7.2 导出名称不匹配
typescript
// 导出时
export { ManagedWebSocket as WSManager };
// 导入时
import { ManagedWebSocket } from './file'; // ❌ 错误
import { WSManager } from './file'; // ✅ 正确
7.3 循环依赖
typescript
// file-a.ts
import { something } from './file-b';
export class ClassA { }
// file-b.ts
import { ClassA } from './file-a'; // ❌ 循环依赖
8. 总结
关键点:
-
必须导出:类、接口、函数等需要跨文件使用时必须使用
export -
模块作用域:每个文件都是独立模块,默认情况下外部无法访问
-
按需导出:只导出需要公开的 API,保持内部实现私有
-
一致性:保持导出/导入风格一致
简单记忆:
-
想在其他文件使用 → 加
export -
想在当前文件使用其他文件的代码 → 加
import -
保持接口最小化 → 只导出必要的部分
这就是现代 JavaScript/TypeScript 模块系统的工作原理!
5万+

被折叠的 条评论
为什么被折叠?



