@yh-ui/request 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +274 -0
- package/dist/adapters/fetch.cjs +157 -0
- package/dist/adapters/fetch.d.ts +25 -0
- package/dist/adapters/fetch.mjs +148 -0
- package/dist/adapters/index.cjs +27 -0
- package/dist/adapters/index.d.ts +5 -0
- package/dist/adapters/index.mjs +2 -0
- package/dist/adapters/platform.cjs +394 -0
- package/dist/adapters/platform.d.ts +72 -0
- package/dist/adapters/platform.mjs +369 -0
- package/dist/cache/index.cjs +56 -0
- package/dist/cache/index.d.ts +21 -0
- package/dist/cache/index.mjs +14 -0
- package/dist/cache/indexedDB.cjs +188 -0
- package/dist/cache/indexedDB.d.ts +58 -0
- package/dist/cache/indexedDB.mjs +176 -0
- package/dist/cache/localStorage.cjs +158 -0
- package/dist/cache/localStorage.d.ts +58 -0
- package/dist/cache/localStorage.mjs +153 -0
- package/dist/cache/memory.cjs +112 -0
- package/dist/cache/memory.d.ts +71 -0
- package/dist/cache/memory.mjs +103 -0
- package/dist/graphql.cjs +255 -0
- package/dist/graphql.d.ts +192 -0
- package/dist/graphql.mjs +235 -0
- package/dist/http-cache.cjs +248 -0
- package/dist/http-cache.d.ts +156 -0
- package/dist/http-cache.mjs +233 -0
- package/dist/index.cjs +181 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.mjs +16 -0
- package/dist/interceptors/debug.cjs +139 -0
- package/dist/interceptors/debug.d.ts +92 -0
- package/dist/interceptors/debug.mjs +130 -0
- package/dist/interceptors/index.cjs +38 -0
- package/dist/interceptors/index.d.ts +6 -0
- package/dist/interceptors/index.mjs +3 -0
- package/dist/interceptors/progress.cjs +185 -0
- package/dist/interceptors/progress.d.ts +97 -0
- package/dist/interceptors/progress.mjs +177 -0
- package/dist/interceptors/security.cjs +154 -0
- package/dist/interceptors/security.d.ts +83 -0
- package/dist/interceptors/security.mjs +134 -0
- package/dist/plugin.cjs +166 -0
- package/dist/plugin.d.ts +106 -0
- package/dist/plugin.mjs +163 -0
- package/dist/request.cjs +396 -0
- package/dist/request.d.ts +111 -0
- package/dist/request.mjs +339 -0
- package/dist/types.cjs +13 -0
- package/dist/types.d.ts +157 -0
- package/dist/types.mjs +7 -0
- package/dist/useAIStream.cjs +125 -0
- package/dist/useAIStream.d.ts +89 -0
- package/dist/useAIStream.mjs +108 -0
- package/dist/useLoadMore.cjs +136 -0
- package/dist/useLoadMore.d.ts +84 -0
- package/dist/useLoadMore.mjs +134 -0
- package/dist/usePagination.cjs +141 -0
- package/dist/usePagination.d.ts +89 -0
- package/dist/usePagination.mjs +132 -0
- package/dist/useQueue.cjs +243 -0
- package/dist/useQueue.d.ts +118 -0
- package/dist/useQueue.mjs +239 -0
- package/dist/useRequest.cjs +325 -0
- package/dist/useRequest.d.ts +126 -0
- package/dist/useRequest.mjs +329 -0
- package/dist/useRequestQueue.cjs +36 -0
- package/dist/useRequestQueue.d.ts +52 -0
- package/dist/useRequestQueue.mjs +27 -0
- package/dist/useSSE.cjs +241 -0
- package/dist/useSSE.d.ts +74 -0
- package/dist/useSSE.mjs +226 -0
- package/dist/websocket.cjs +325 -0
- package/dist/websocket.d.ts +163 -0
- package/dist/websocket.mjs +316 -0
- package/package.json +61 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket 支持
|
|
3
|
+
* 提供 WebSocket 连接管理、自动重连、心跳检测等功能
|
|
4
|
+
*/
|
|
5
|
+
import { type Ref } from 'vue';
|
|
6
|
+
/** WebSocket 状态 */
|
|
7
|
+
export type WebSocketState = 'connecting' | 'connected' | 'disconnecting' | 'disconnected' | 'reconnecting' | 'error';
|
|
8
|
+
/** WebSocket 消息数据 */
|
|
9
|
+
export type WebSocketData = string | ArrayBuffer | Blob;
|
|
10
|
+
/** WebSocket 消息 */
|
|
11
|
+
export interface WebSocketMessage<T = unknown> {
|
|
12
|
+
/** 消息类型 */
|
|
13
|
+
type: 'text' | 'binary' | 'ping' | 'pong' | 'error';
|
|
14
|
+
/** 消息数据 */
|
|
15
|
+
data: T;
|
|
16
|
+
/** 原始数据 */
|
|
17
|
+
raw: WebSocketData;
|
|
18
|
+
/** 时间戳 */
|
|
19
|
+
timestamp: number;
|
|
20
|
+
}
|
|
21
|
+
/** WebSocket 配置 */
|
|
22
|
+
export interface WebSocketOptions {
|
|
23
|
+
/** WebSocket URL */
|
|
24
|
+
url: string;
|
|
25
|
+
/** 协议子数组 */
|
|
26
|
+
protocols?: string | string[];
|
|
27
|
+
/** 自动重连 */
|
|
28
|
+
reconnect?: boolean;
|
|
29
|
+
/** 重连最大次数 */
|
|
30
|
+
reconnectMaxAttempts?: number;
|
|
31
|
+
/** 重连初始延迟 (ms) */
|
|
32
|
+
reconnectInterval?: number;
|
|
33
|
+
/** 重连最大延迟 (ms) */
|
|
34
|
+
reconnectMaxDelay?: number;
|
|
35
|
+
/** 心跳启用 */
|
|
36
|
+
heartbeat?: boolean;
|
|
37
|
+
/** 心跳间隔 (ms) */
|
|
38
|
+
heartbeatInterval?: number;
|
|
39
|
+
/** 心跳超时 (ms) */
|
|
40
|
+
heartbeatTimeout?: number;
|
|
41
|
+
/** 自定义请求头 (仅浏览器) */
|
|
42
|
+
headers?: Record<string, string>;
|
|
43
|
+
/** 二进制数据类型 */
|
|
44
|
+
binaryType?: BinaryType;
|
|
45
|
+
/** 消息编码器 */
|
|
46
|
+
encode?: (data: unknown) => string | ArrayBuffer;
|
|
47
|
+
/** 消息解码器 */
|
|
48
|
+
decode?: (data: WebSocketData) => unknown;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* WebSocket 客户端类
|
|
52
|
+
* 支持自动重连、心跳检测、消息队列等功能
|
|
53
|
+
*/
|
|
54
|
+
export declare class WebSocketClient {
|
|
55
|
+
private ws;
|
|
56
|
+
private url;
|
|
57
|
+
private protocols?;
|
|
58
|
+
private options;
|
|
59
|
+
private _state;
|
|
60
|
+
private reconnectAttempts;
|
|
61
|
+
private reconnectTimer;
|
|
62
|
+
private heartbeatTimer;
|
|
63
|
+
private heartbeatTimeoutTimer;
|
|
64
|
+
private messageQueue;
|
|
65
|
+
private onOpenCallback;
|
|
66
|
+
private onCloseCallback;
|
|
67
|
+
private onErrorCallback;
|
|
68
|
+
private onMessageCallback;
|
|
69
|
+
private onStateChangeCallback;
|
|
70
|
+
readonly state: Ref<WebSocketState>;
|
|
71
|
+
readonly isConnected: Ref<boolean>;
|
|
72
|
+
readonly lastMessage: Ref<WebSocketMessage | null>;
|
|
73
|
+
constructor(options: WebSocketOptions);
|
|
74
|
+
/**
|
|
75
|
+
* 获取当前状态
|
|
76
|
+
*/
|
|
77
|
+
getState(): WebSocketState;
|
|
78
|
+
/**
|
|
79
|
+
* 设置状态
|
|
80
|
+
*/
|
|
81
|
+
private setState;
|
|
82
|
+
/**
|
|
83
|
+
* 连接
|
|
84
|
+
*/
|
|
85
|
+
connect(): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* 断开连接
|
|
88
|
+
*/
|
|
89
|
+
disconnect(code?: number, reason?: string): void;
|
|
90
|
+
/**
|
|
91
|
+
* 发送消息
|
|
92
|
+
*/
|
|
93
|
+
send(data: unknown): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* 发送并等待响应
|
|
96
|
+
*/
|
|
97
|
+
sendAndWait<T = unknown>(data: unknown, timeout?: number): Promise<T>;
|
|
98
|
+
/**
|
|
99
|
+
* 事件回调
|
|
100
|
+
*/
|
|
101
|
+
onOpen(callback: () => void): this;
|
|
102
|
+
onClose(callback: (code: number, reason: string) => void): this;
|
|
103
|
+
onError(callback: (error: Event) => void): this;
|
|
104
|
+
onMessage(callback: (message: WebSocketMessage) => void): this;
|
|
105
|
+
onStateChange(callback: (state: WebSocketState) => void): this;
|
|
106
|
+
private handleOpen;
|
|
107
|
+
private handleClose;
|
|
108
|
+
private handleError;
|
|
109
|
+
private handleMessage;
|
|
110
|
+
private reconnect;
|
|
111
|
+
private startHeartbeat;
|
|
112
|
+
private clearHeartbeatTimeout;
|
|
113
|
+
private clearTimers;
|
|
114
|
+
/**
|
|
115
|
+
* 清理资源
|
|
116
|
+
*/
|
|
117
|
+
dispose(): void;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* WebSocket Vue Hook
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* const {
|
|
124
|
+
* state, isConnected, lastMessage,
|
|
125
|
+
* connect, disconnect, send
|
|
126
|
+
* } = useWebSocket({
|
|
127
|
+
* url: 'wss://example.com/ws',
|
|
128
|
+
* reconnect: true,
|
|
129
|
+
* heartbeat: true,
|
|
130
|
+
* })
|
|
131
|
+
*/
|
|
132
|
+
export declare function useWebSocket(options: WebSocketOptions): {
|
|
133
|
+
/** 当前状态 */
|
|
134
|
+
state: Ref<WebSocketState, WebSocketState>;
|
|
135
|
+
/** 是否已连接 */
|
|
136
|
+
isConnected: Ref<boolean, boolean>;
|
|
137
|
+
/** 最后收到的消息 */
|
|
138
|
+
lastMessage: Ref<WebSocketMessage<unknown> | null, WebSocketMessage<unknown> | null>;
|
|
139
|
+
/** 连接 */
|
|
140
|
+
connect: () => Promise<void>;
|
|
141
|
+
/** 断开连接 */
|
|
142
|
+
disconnect: (code?: number, reason?: string) => void;
|
|
143
|
+
/** 发送消息 */
|
|
144
|
+
send: (data: unknown) => boolean;
|
|
145
|
+
/** 发送并等待响应 */
|
|
146
|
+
sendAndWait: <T = unknown>(data: unknown, timeout?: number) => Promise<T>;
|
|
147
|
+
/** 事件监听 */
|
|
148
|
+
onOpen: (callback: () => void) => WebSocketClient;
|
|
149
|
+
onClose: (callback: (code: number, reason: string) => void) => WebSocketClient;
|
|
150
|
+
onError: (callback: (error: Event) => void) => WebSocketClient;
|
|
151
|
+
onMessage: (callback: (message: WebSocketMessage) => void) => WebSocketClient;
|
|
152
|
+
onStateChange: (callback: (state: WebSocketState) => void) => WebSocketClient;
|
|
153
|
+
/** 获取原始客户端 */
|
|
154
|
+
getClient: () => WebSocketClient;
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* 创建 WebSocket 客户端
|
|
158
|
+
*/
|
|
159
|
+
export declare function createWebSocket(options: WebSocketOptions): WebSocketClient;
|
|
160
|
+
/**
|
|
161
|
+
* 判断浏览器是否支持 WebSocket
|
|
162
|
+
*/
|
|
163
|
+
export declare function isWebSocketSupported(): boolean;
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { ref, onUnmounted } from "vue";
|
|
2
|
+
export class WebSocketClient {
|
|
3
|
+
ws = null;
|
|
4
|
+
url = "";
|
|
5
|
+
protocols;
|
|
6
|
+
options;
|
|
7
|
+
// 状态
|
|
8
|
+
_state = "disconnected";
|
|
9
|
+
reconnectAttempts = 0;
|
|
10
|
+
reconnectTimer = null;
|
|
11
|
+
heartbeatTimer = null;
|
|
12
|
+
heartbeatTimeoutTimer = null;
|
|
13
|
+
messageQueue = [];
|
|
14
|
+
// 回调
|
|
15
|
+
onOpenCallback = null;
|
|
16
|
+
onCloseCallback = null;
|
|
17
|
+
onErrorCallback = null;
|
|
18
|
+
onMessageCallback = null;
|
|
19
|
+
onStateChangeCallback = null;
|
|
20
|
+
// 响应式状态 (供 Vue 使用)
|
|
21
|
+
state;
|
|
22
|
+
isConnected;
|
|
23
|
+
lastMessage;
|
|
24
|
+
constructor(options) {
|
|
25
|
+
this.url = options.url;
|
|
26
|
+
this.protocols = options.protocols;
|
|
27
|
+
this.options = {
|
|
28
|
+
url: options.url,
|
|
29
|
+
protocols: options.protocols,
|
|
30
|
+
reconnect: options.reconnect ?? true,
|
|
31
|
+
reconnectMaxAttempts: options.reconnectMaxAttempts ?? 10,
|
|
32
|
+
reconnectInterval: options.reconnectInterval ?? 1e3,
|
|
33
|
+
reconnectMaxDelay: options.reconnectMaxDelay ?? 3e4,
|
|
34
|
+
heartbeat: options.heartbeat ?? false,
|
|
35
|
+
heartbeatInterval: options.heartbeatInterval ?? 3e4,
|
|
36
|
+
heartbeatTimeout: options.heartbeatTimeout ?? 1e4,
|
|
37
|
+
headers: options.headers ?? {},
|
|
38
|
+
binaryType: options.binaryType ?? "blob",
|
|
39
|
+
encode: options.encode ?? ((data) => JSON.stringify(data)),
|
|
40
|
+
decode: options.decode ?? ((data) => {
|
|
41
|
+
if (typeof data === "string") {
|
|
42
|
+
try {
|
|
43
|
+
return JSON.parse(data);
|
|
44
|
+
} catch {
|
|
45
|
+
return data;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return data;
|
|
49
|
+
})
|
|
50
|
+
};
|
|
51
|
+
this.state = ref("disconnected");
|
|
52
|
+
this.isConnected = ref(false);
|
|
53
|
+
this.lastMessage = ref(null);
|
|
54
|
+
this.handleOpen = this.handleOpen.bind(this);
|
|
55
|
+
this.handleClose = this.handleClose.bind(this);
|
|
56
|
+
this.handleError = this.handleError.bind(this);
|
|
57
|
+
this.handleMessage = this.handleMessage.bind(this);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 获取当前状态
|
|
61
|
+
*/
|
|
62
|
+
getState() {
|
|
63
|
+
return this._state;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 设置状态
|
|
67
|
+
*/
|
|
68
|
+
setState(newState) {
|
|
69
|
+
this._state = newState;
|
|
70
|
+
this.state.value = newState;
|
|
71
|
+
this.isConnected.value = newState === "connected";
|
|
72
|
+
this.onStateChangeCallback?.(newState);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* 连接
|
|
76
|
+
*/
|
|
77
|
+
connect() {
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
if (!isWebSocketSupported()) {
|
|
80
|
+
const error = new Error("WebSocket is not supported in this environment");
|
|
81
|
+
this.setState("error");
|
|
82
|
+
reject(error);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const CONNECTING = 0;
|
|
86
|
+
const OPEN = 1;
|
|
87
|
+
if (this.ws && (this.ws.readyState === OPEN || this.ws.readyState === CONNECTING)) {
|
|
88
|
+
resolve();
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
this.setState("connecting");
|
|
92
|
+
try {
|
|
93
|
+
this.ws = this.protocols ? new WebSocket(this.url, this.protocols) : new WebSocket(this.url);
|
|
94
|
+
this.ws.binaryType = this.options.binaryType;
|
|
95
|
+
this.ws.onopen = (event) => {
|
|
96
|
+
this.handleOpen(event);
|
|
97
|
+
resolve();
|
|
98
|
+
};
|
|
99
|
+
this.ws.onclose = this.handleClose;
|
|
100
|
+
this.ws.onerror = this.handleError;
|
|
101
|
+
this.ws.onmessage = this.handleMessage;
|
|
102
|
+
} catch (error) {
|
|
103
|
+
this.setState("error");
|
|
104
|
+
reject(error);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* 断开连接
|
|
110
|
+
*/
|
|
111
|
+
disconnect(code = 1e3, reason = "Client disconnect") {
|
|
112
|
+
this.clearTimers();
|
|
113
|
+
this.setState("disconnecting");
|
|
114
|
+
if (this.ws) {
|
|
115
|
+
this.ws.close(code, reason);
|
|
116
|
+
this.ws = null;
|
|
117
|
+
}
|
|
118
|
+
this.setState("disconnected");
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* 发送消息
|
|
122
|
+
*/
|
|
123
|
+
send(data) {
|
|
124
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
125
|
+
this.messageQueue.push(this.options.encode(data));
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
const encoded = this.options.encode(data);
|
|
129
|
+
this.ws.send(encoded);
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* 发送并等待响应
|
|
134
|
+
*/
|
|
135
|
+
sendAndWait(data, timeout = 3e4) {
|
|
136
|
+
return new Promise((resolve, reject) => {
|
|
137
|
+
const messageId = Date.now().toString();
|
|
138
|
+
const timer = setTimeout(() => {
|
|
139
|
+
reject(new Error("WebSocket message timeout"));
|
|
140
|
+
}, timeout);
|
|
141
|
+
const originalCallback = this.onMessageCallback;
|
|
142
|
+
this.onMessageCallback = (message) => {
|
|
143
|
+
const decoded = message.data;
|
|
144
|
+
if (decoded && decoded.id === messageId) {
|
|
145
|
+
clearTimeout(timer);
|
|
146
|
+
this.onMessageCallback = originalCallback;
|
|
147
|
+
resolve(decoded.result);
|
|
148
|
+
} else {
|
|
149
|
+
originalCallback?.(message);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
this.send({ id: messageId, ...data });
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* 事件回调
|
|
157
|
+
*/
|
|
158
|
+
onOpen(callback) {
|
|
159
|
+
this.onOpenCallback = callback;
|
|
160
|
+
return this;
|
|
161
|
+
}
|
|
162
|
+
onClose(callback) {
|
|
163
|
+
this.onCloseCallback = callback;
|
|
164
|
+
return this;
|
|
165
|
+
}
|
|
166
|
+
onError(callback) {
|
|
167
|
+
this.onErrorCallback = callback;
|
|
168
|
+
return this;
|
|
169
|
+
}
|
|
170
|
+
onMessage(callback) {
|
|
171
|
+
this.onMessageCallback = callback;
|
|
172
|
+
return this;
|
|
173
|
+
}
|
|
174
|
+
onStateChange(callback) {
|
|
175
|
+
this.onStateChangeCallback = callback;
|
|
176
|
+
return this;
|
|
177
|
+
}
|
|
178
|
+
// ==================== 内部方法 ====================
|
|
179
|
+
handleOpen(_event) {
|
|
180
|
+
this.setState("connected");
|
|
181
|
+
this.reconnectAttempts = 0;
|
|
182
|
+
while (this.messageQueue.length > 0) {
|
|
183
|
+
const data = this.messageQueue.shift();
|
|
184
|
+
if (data && this.ws) {
|
|
185
|
+
this.ws.send(data);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (this.options.heartbeat) {
|
|
189
|
+
this.startHeartbeat();
|
|
190
|
+
}
|
|
191
|
+
this.onOpenCallback?.();
|
|
192
|
+
}
|
|
193
|
+
handleClose(event) {
|
|
194
|
+
this.ws = null;
|
|
195
|
+
this.clearTimers();
|
|
196
|
+
this.setState("disconnected");
|
|
197
|
+
if (this.options.reconnect && this.reconnectAttempts < this.options.reconnectMaxAttempts) {
|
|
198
|
+
this.reconnect();
|
|
199
|
+
}
|
|
200
|
+
this.onCloseCallback?.(event.code, event.reason);
|
|
201
|
+
}
|
|
202
|
+
handleError(event) {
|
|
203
|
+
this.setState("error");
|
|
204
|
+
this.onErrorCallback?.(event);
|
|
205
|
+
}
|
|
206
|
+
handleMessage(event) {
|
|
207
|
+
const raw = event.data;
|
|
208
|
+
let data;
|
|
209
|
+
if (event.data === "pong") {
|
|
210
|
+
this.clearHeartbeatTimeout();
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
try {
|
|
214
|
+
data = this.options.decode(raw);
|
|
215
|
+
} catch {
|
|
216
|
+
data = raw;
|
|
217
|
+
}
|
|
218
|
+
const message = {
|
|
219
|
+
type: event.data instanceof ArrayBuffer || event.data instanceof Blob ? "binary" : "text",
|
|
220
|
+
data,
|
|
221
|
+
raw,
|
|
222
|
+
timestamp: Date.now()
|
|
223
|
+
};
|
|
224
|
+
this.lastMessage.value = message;
|
|
225
|
+
this.onMessageCallback?.(message);
|
|
226
|
+
}
|
|
227
|
+
reconnect() {
|
|
228
|
+
this.setState("reconnecting");
|
|
229
|
+
this.reconnectAttempts++;
|
|
230
|
+
const delay = Math.min(
|
|
231
|
+
this.options.reconnectInterval * Math.pow(2, this.reconnectAttempts - 1),
|
|
232
|
+
this.options.reconnectMaxDelay
|
|
233
|
+
);
|
|
234
|
+
this.reconnectTimer = setTimeout(() => {
|
|
235
|
+
this.connect().catch(() => {
|
|
236
|
+
});
|
|
237
|
+
}, delay);
|
|
238
|
+
}
|
|
239
|
+
startHeartbeat() {
|
|
240
|
+
this.heartbeatTimer = setInterval(() => {
|
|
241
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
242
|
+
this.ws.send("ping");
|
|
243
|
+
this.heartbeatTimeoutTimer = setTimeout(() => {
|
|
244
|
+
this.disconnect(4e3, "Heartbeat timeout");
|
|
245
|
+
}, this.options.heartbeatTimeout);
|
|
246
|
+
}
|
|
247
|
+
}, this.options.heartbeatInterval);
|
|
248
|
+
}
|
|
249
|
+
clearHeartbeatTimeout() {
|
|
250
|
+
if (this.heartbeatTimeoutTimer) {
|
|
251
|
+
clearTimeout(this.heartbeatTimeoutTimer);
|
|
252
|
+
this.heartbeatTimeoutTimer = null;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
clearTimers() {
|
|
256
|
+
if (this.reconnectTimer) {
|
|
257
|
+
clearTimeout(this.reconnectTimer);
|
|
258
|
+
this.reconnectTimer = null;
|
|
259
|
+
}
|
|
260
|
+
if (this.heartbeatTimer) {
|
|
261
|
+
clearInterval(this.heartbeatTimer);
|
|
262
|
+
this.heartbeatTimer = null;
|
|
263
|
+
}
|
|
264
|
+
this.clearHeartbeatTimeout();
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* 清理资源
|
|
268
|
+
*/
|
|
269
|
+
dispose() {
|
|
270
|
+
this.disconnect();
|
|
271
|
+
this.onOpenCallback = null;
|
|
272
|
+
this.onCloseCallback = null;
|
|
273
|
+
this.onErrorCallback = null;
|
|
274
|
+
this.onMessageCallback = null;
|
|
275
|
+
this.onStateChangeCallback = null;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
export function useWebSocket(options) {
|
|
279
|
+
const client = new WebSocketClient(options);
|
|
280
|
+
const state = client.state;
|
|
281
|
+
const isConnected = client.isConnected;
|
|
282
|
+
const lastMessage = client.lastMessage;
|
|
283
|
+
onUnmounted(() => {
|
|
284
|
+
client.dispose();
|
|
285
|
+
});
|
|
286
|
+
return {
|
|
287
|
+
/** 当前状态 */
|
|
288
|
+
state,
|
|
289
|
+
/** 是否已连接 */
|
|
290
|
+
isConnected,
|
|
291
|
+
/** 最后收到的消息 */
|
|
292
|
+
lastMessage,
|
|
293
|
+
/** 连接 */
|
|
294
|
+
connect: () => client.connect(),
|
|
295
|
+
/** 断开连接 */
|
|
296
|
+
disconnect: (code, reason) => client.disconnect(code, reason),
|
|
297
|
+
/** 发送消息 */
|
|
298
|
+
send: (data) => client.send(data),
|
|
299
|
+
/** 发送并等待响应 */
|
|
300
|
+
sendAndWait: (data, timeout) => client.sendAndWait(data, timeout),
|
|
301
|
+
/** 事件监听 */
|
|
302
|
+
onOpen: (callback) => client.onOpen(callback),
|
|
303
|
+
onClose: (callback) => client.onClose(callback),
|
|
304
|
+
onError: (callback) => client.onError(callback),
|
|
305
|
+
onMessage: (callback) => client.onMessage(callback),
|
|
306
|
+
onStateChange: (callback) => client.onStateChange(callback),
|
|
307
|
+
/** 获取原始客户端 */
|
|
308
|
+
getClient: () => client
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
export function createWebSocket(options) {
|
|
312
|
+
return new WebSocketClient(options);
|
|
313
|
+
}
|
|
314
|
+
export function isWebSocketSupported() {
|
|
315
|
+
return typeof WebSocket !== "undefined";
|
|
316
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yh-ui/request",
|
|
3
|
+
"version": "0.1.21",
|
|
4
|
+
"description": "YH-UI HTTP request hooks - Enterprise-grade request management",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.mjs",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.mjs",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
},
|
|
16
|
+
"./*": {
|
|
17
|
+
"types": "./dist/*.d.ts",
|
|
18
|
+
"import": "./dist/*.mjs",
|
|
19
|
+
"require": "./dist/*.cjs"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@yh-ui/utils": "0.1.21"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"vue": "^3.5.27",
|
|
30
|
+
"vue-tsc": "^2.2.0"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"vue": "^3.5.27"
|
|
34
|
+
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/1079161148/yh-ui.git",
|
|
41
|
+
"directory": "packages/request"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"yh-ui",
|
|
45
|
+
"request",
|
|
46
|
+
"http",
|
|
47
|
+
"fetch",
|
|
48
|
+
"hooks",
|
|
49
|
+
"sse",
|
|
50
|
+
"streaming"
|
|
51
|
+
],
|
|
52
|
+
"homepage": "https://1079161148.github.io/yh-ui/",
|
|
53
|
+
"author": "YH-UI Team",
|
|
54
|
+
"license": "MIT",
|
|
55
|
+
"scripts": {
|
|
56
|
+
"build": "unbuild",
|
|
57
|
+
"dev": "unbuild --stub",
|
|
58
|
+
"typecheck": "vue-tsc --noEmit",
|
|
59
|
+
"lint": "eslint ."
|
|
60
|
+
}
|
|
61
|
+
}
|