Ver código fonte

chron:refactor dir struct

Paul 5 anos atrás
pai
commit
73d14f0592
4 arquivos alterados com 438 adições e 436 exclusões
  1. 2
    2
      example/main.ts
  2. 0
    431
      src/client.ts
  3. 430
    3
      src/index.ts
  4. 6
    0
      src/types/index.ts

+ 2
- 2
example/main.ts Ver arquivo

@@ -1,5 +1,5 @@
1
-import { Client, WebSocketResp } from '../src/client';
2
-import { WebsocketError } from './error';
1
+import { Client } from '../src/';
2
+import { WebsocketError, WebSocketResp } from '../src/types';
3 3
 
4 4
 const url = 'ws://127.0.0.1:8081';
5 5
 const client = new Client(url, {

+ 0
- 431
src/client.ts Ver arquivo

@@ -1,431 +0,0 @@
1
-import { Packet } from './packet';
2
-import { Utils } from './utils';
3
-import { ReadyStateCallback } from './types/callback';
4
-import { WebsocketError } from './error';
5
-
6
-const clientError = 400;
7
-
8
-export interface WebSocketResp {
9
-  value: object | string;
10
-}
11
-
12
-/**
13
- * 初始化链接以及收发数据
14
- */
15
-class Client {
16
-  private _maxPayload: number;
17
-  private _enableLogger: boolean;
18
-  private listeners: Map<number, (data: WebSocketResp) => void>;
19
-  private requestHeader: string;
20
-  private responseHeader: string;
21
-  private url: string;
22
-  private reconnectTimes: number;
23
-  private reconnectLock: boolean;
24
-  private socket: WebSocket;
25
-  private readyStateCallback: ReadyStateCallback;
26
-
27
-  /**
28
-   * 构造函数,初始化客户端链接
29
-   * @param url websocket链接地址
30
-   * @param readyStateCallback 链接状态回调,可以处理onOpen、onClose、onError
31
-   */
32
-  public constructor(url: string, readyStateCallback: ReadyStateCallback) {
33
-    this.listeners = new Map<number, (data: WebSocketResp) => void>();
34
-    this.requestHeader = '';
35
-    this.requestHeader = '';
36
-    this._maxPayload = 1024 * 1024;
37
-    this.url = url;
38
-    this.reconnectTimes = 0;
39
-    this.readyStateCallback = readyStateCallback;
40
-    this._enableLogger = false;
41
-    this.socket = this.connect();
42
-  }
43
-
44
-  /**
45
-   * 设置可以处理的数据包上限
46
-   * @param maxPayload 最多可以处理的数据包大小
47
-   */
48
-  public set maxPayload(maxPayload: number) {
49
-    this._maxPayload = maxPayload;
50
-  }
51
-
52
-  /**
53
-   * 获取可以处理的数据包大小
54
-   */
55
-  public get maxPayload(): number {
56
-    return this._maxPayload;
57
-  }
58
-
59
-  /**
60
-   * 设置是否允许显示运行日志
61
-   */
62
-  public set enableLogger(enableLogger: boolean) {
63
-    this._enableLogger = enableLogger;
64
-  }
65
-
66
-  /**
67
-   * 获取是否显示日志的配置信息
68
-   */
69
-  public get enableLogger(): boolean {
70
-    return this._enableLogger;
71
-  }
72
-
73
-  /**
74
-   * 发送ping请求,来保持长连接
75
-   * @param param 请求参数,比如{"hello":"world"}
76
-   */
77
-  public async ping(param: object): Promise<WebSocketResp> {
78
-    return new Promise(
79
-      (
80
-        resolve: (data: WebSocketResp) => void,
81
-        reject: (err: WebsocketError) => void,
82
-      ): void => {
83
-        if (this.socket.readyState !== this.socket.OPEN) {
84
-          if (this._enableLogger) {
85
-            console.log('[ping]: connection refuse');
86
-          }
87
-
88
-          reject(new WebsocketError(clientError, 'connection refuse'));
89
-        }
90
-
91
-        const heartbeatOperator = 0;
92
-
93
-        this.listeners.set(
94
-          heartbeatOperator,
95
-          (data: WebSocketResp): void => {
96
-            const code = this.getResponseProperty('code');
97
-            if (code !== '') {
98
-              const message = this.getResponseProperty('message');
99
-              reject(new WebsocketError(Number(code), message));
100
-            } else {
101
-              resolve(data);
102
-            }
103
-          },
104
-        );
105
-
106
-        const p = new Packet();
107
-        this.send(
108
-          p.pack(
109
-            heartbeatOperator,
110
-            0,
111
-            this.requestHeader,
112
-            JSON.stringify(param),
113
-          ),
114
-        );
115
-
116
-        if (this._enableLogger) {
117
-          console.info(
118
-            '[send data packet]',
119
-            heartbeatOperator,
120
-            0,
121
-            this.requestHeader,
122
-            param,
123
-          );
124
-        }
125
-      },
126
-    );
127
-  }
128
-
129
-  /**
130
-   * 同步方式向服务端发送请求
131
-   * @param operator 路由地址
132
-   * @param param 请求参数,比如{"hello":"world"}
133
-   * @param callback 请求状态回调处理
134
-   */
135
-  public async request(
136
-    operator: string,
137
-    param: object,
138
-  ): Promise<WebSocketResp> {
139
-    return await this.asyncSend(operator, param);
140
-  }
141
-
142
-  /**
143
-   * 添加消息监听
144
-   * @description 添加消息监听器,比如operator是/v1/message/listener,那么从服务端推送到/v1/message/listener的消息会进入到定义的listener里面进行处理
145
-   * @param operator 消息监听地址
146
-   * @param listener 定义如何处理从服务端返回的消息
147
-   */
148
-  public addMessageListener(
149
-    operator: string,
150
-    listener: (data: WebSocketResp) => void,
151
-  ): void {
152
-    this.listeners.set(Utils.crc32(operator), listener);
153
-  }
154
-
155
-  /**
156
-   * 移除消息监听
157
-   * @param operator 消息监听地址
158
-   */
159
-  public removeMessageListener(operator: string): void {
160
-    delete this.listeners[Utils.crc32(operator)];
161
-  }
162
-
163
-  /**
164
-   * 返回Websocket链接状态
165
-   * @returns Websocket的链接状态
166
-   */
167
-  public get readyState(): number {
168
-    return this.socket.readyState;
169
-  }
170
-
171
-  /**
172
-   * 添加请求属性,会携带在数据帧里面发送到服务端
173
-   * @param key 属性名
174
-   * @param value 属性值
175
-   */
176
-  public setRequestProperty(key: string, value: string): void {
177
-    let v = this.getRequestProperty(key);
178
-
179
-    this.requestHeader = this.requestHeader.replace(key + '=' + v + ';', '');
180
-    this.requestHeader = this.requestHeader + key + '=' + value + ';';
181
-  }
182
-
183
-  /**
184
-   * 获取请求属性
185
-   * @param key 属性名
186
-   */
187
-  public getRequestProperty(key: string): string {
188
-    if (this.requestHeader !== undefined) {
189
-      let values = this.requestHeader.split(';');
190
-      for (let index in values) {
191
-        let kv = values[index].split('=');
192
-        if (kv[0] === key) {
193
-          return kv[1];
194
-        }
195
-      }
196
-    }
197
-
198
-    return '';
199
-  }
200
-
201
-  /**
202
-   * 设置响应属性,客户端基本用不到,都是服务端来进行设置
203
-   * @param key 属性名
204
-   * @param value 属性值
205
-   */
206
-  public setResponseProperty(key: string, value: string): void {
207
-    let v = this.getResponseProperty(key);
208
-
209
-    this.responseHeader = this.responseHeader.replace(key + '=' + v + ';', '');
210
-    this.responseHeader = this.responseHeader + key + '=' + value + ';';
211
-  }
212
-
213
-  /**
214
-   * 获取从服务端返回的属性
215
-   * @param key 获取响应属性
216
-   */
217
-  public getResponseProperty(key: string): string {
218
-    if (this.responseHeader !== undefined) {
219
-      let values = this.responseHeader.split(';');
220
-      for (let index in values) {
221
-        let kv = values[index].split('=');
222
-        if (kv[0] === key) {
223
-          return kv[1];
224
-        }
225
-      }
226
-    }
227
-
228
-    return '';
229
-  }
230
-  /**
231
-   * 关闭客户端链接
232
-   */
233
-  public close(code?: number, reason?: string): void {
234
-    this.socket.close(code, reason);
235
-  }
236
-  /**
237
-   * 创建websocket链接
238
-   */
239
-  private connect(): WebSocket {
240
-    const readyStateCallback = this.readyStateCallback;
241
-    let ws = new WebSocket(this.url);
242
-
243
-    ws.binaryType = 'blob';
244
-
245
-    ws.onopen = (ev): void => {
246
-      if (this._enableLogger) {
247
-        console.info('[websocket] open connection');
248
-      }
249
-
250
-      this.reconnectTimes = 0;
251
-
252
-      readyStateCallback.onOpen(ev);
253
-    };
254
-
255
-    ws.onclose = (ev): void => {
256
-      if (this._enableLogger) {
257
-        console.info('[websocket] close connection');
258
-      }
259
-
260
-      this.reconnect();
261
-
262
-      readyStateCallback.onClose(ev);
263
-    };
264
-
265
-    ws.onerror = (ev): void => {
266
-      if (this._enableLogger) {
267
-        console.info('[websocket] error');
268
-      }
269
-
270
-      this.reconnect();
271
-
272
-      readyStateCallback.onError(ev);
273
-    };
274
-
275
-    ws.onmessage = (ev): void => {
276
-      if (ev.data instanceof Blob) {
277
-        let reader = new FileReader();
278
-        reader.readAsArrayBuffer(ev.data);
279
-        reader.onload = (): void => {
280
-          try {
281
-            let packet = new Packet().unPack(reader.result as ArrayBuffer);
282
-            let packetLength = packet.headerLength + packet.bodyLength + 20;
283
-            if (packetLength > this._maxPayload) {
284
-              throw new Error('the packet is big than ' + this._maxPayload);
285
-            }
286
-
287
-            let operator = Number(packet.operator) + Number(packet.sequence);
288
-            if (this.listeners.has(operator)) {
289
-              if (packet.body === '') {
290
-                packet.body = '{}';
291
-              }
292
-
293
-              this.responseHeader = packet.header;
294
-
295
-              (this.listeners.get(operator) as (data: WebSocketResp) => void)(
296
-                JSON.parse(packet.body),
297
-              );
298
-            }
299
-
300
-            if (this._enableLogger) {
301
-              if (operator !== 0 && packet.body !== 'null') {
302
-                console.info('receive data packet', packet.body);
303
-              }
304
-            }
305
-          } catch (e) {
306
-            throw new Error(e);
307
-          }
308
-        };
309
-      } else {
310
-        throw new Error('unsupported data format');
311
-      }
312
-    };
313
-
314
-    return ws;
315
-  }
316
-
317
-  /**
318
-   * 断线重连
319
-   */
320
-  private reconnect(): void {
321
-    if (!this.reconnectLock) {
322
-      this.reconnectLock = true;
323
-      if (this._enableLogger) {
324
-        console.info('websocket reconnect in ' + this.reconnectTimes + 's');
325
-      }
326
-
327
-      // 尝试重连
328
-      setTimeout((): void => {
329
-        this.reconnectTimes++;
330
-        this.socket = this.connect();
331
-        this.reconnectLock = false;
332
-      }, this.reconnectTimes * 1000);
333
-    }
334
-  }
335
-
336
-  /**
337
-   * 向服务端发送数据请求
338
-   * @param data 向服务端传送的数据
339
-   */
340
-  private send(data: ArrayBuffer): void {
341
-    if (this.socket.readyState !== this.socket.OPEN) {
342
-      if (this._enableLogger) {
343
-        console.error(
344
-          '[send] WebSocket is already in CLOSING or CLOSED state.',
345
-        );
346
-      }
347
-
348
-      return;
349
-    }
350
-
351
-    try {
352
-      this.socket.send(data);
353
-    } catch (e) {
354
-      throw new Error('send data error' + e);
355
-    }
356
-  }
357
-
358
-  /**
359
-   * 异步向服务端发送请求
360
-   * @param operator 路由地址
361
-   * @param param 请求参数,比如{"hello":"world"}
362
-   * @param callback 请求状态回调处理
363
-   */
364
-  private asyncSend(operator: string, param: object): Promise<WebSocketResp> {
365
-    return new Promise(
366
-      (
367
-        resolve: (data: WebSocketResp) => void,
368
-        reject: (err: WebsocketError) => void,
369
-      ): void => {
370
-        if (this.socket.readyState !== this.socket.OPEN) {
371
-          if (this._enableLogger) {
372
-            console.log('[ping]: connection refuse');
373
-          }
374
-
375
-          reject(
376
-            new WebsocketError(clientError, 'asyncSend: connection refuse'),
377
-          );
378
-        }
379
-
380
-        const sequence = new Date().getTime();
381
-        const listener = Utils.crc32(operator) + sequence;
382
-        this.listeners.set(
383
-          listener,
384
-          (data: WebSocketResp): void => {
385
-            const code = this.getResponseProperty('code');
386
-            if (code !== '') {
387
-              const message = this.getResponseProperty('message');
388
-              reject(new WebsocketError(Number(code), message));
389
-            } else {
390
-              resolve(data);
391
-            }
392
-
393
-            delete this.listeners[listener];
394
-          },
395
-        );
396
-
397
-        const p = new Packet();
398
-        this.send(
399
-          p.pack(
400
-            Utils.crc32(operator),
401
-            sequence,
402
-            this.requestHeader,
403
-            JSON.stringify(param),
404
-          ),
405
-        );
406
-
407
-        if (this._enableLogger) {
408
-          console.info(
409
-            '[send data packet]',
410
-            operator,
411
-            sequence,
412
-            this.requestHeader,
413
-            param,
414
-          );
415
-        }
416
-      },
417
-    );
418
-  }
419
-}
420
-
421
-let client: Client;
422
-
423
-function getClient(url: string, callback: ReadyStateCallback): Client {
424
-  if (!client) {
425
-    client = new Client(url, callback);
426
-  }
427
-
428
-  return client;
429
-}
430
-
431
-export { Client, getClient };

+ 430
- 3
src/index.ts Ver arquivo

@@ -1,3 +1,430 @@
1
-export { WebsocketError } from './error';
2
-export { Client, WebSocketResp, getClient } from './client';
3
-export { ReadyStateCallback } from './types/callback';
1
+import { Packet } from './packet';
2
+import { Utils } from './utils';
3
+import {
4
+  WebsocketError,
5
+  WebSocketResp,
6
+  ReadyStateCallback,
7
+} from './types/index';
8
+
9
+const clientError = 400;
10
+
11
+/**
12
+ * 初始化链接以及收发数据
13
+ */
14
+class Client {
15
+  private _maxPayload: number;
16
+  private _enableLogger: boolean;
17
+  private listeners: Map<number, (data: WebSocketResp) => void>;
18
+  private requestHeader: string;
19
+  private responseHeader: string;
20
+  private url: string;
21
+  private reconnectTimes: number;
22
+  private reconnectLock: boolean;
23
+  private socket: WebSocket;
24
+  private readyStateCallback: ReadyStateCallback;
25
+
26
+  /**
27
+   * 构造函数,初始化客户端链接
28
+   * @param url websocket链接地址
29
+   * @param readyStateCallback 链接状态回调,可以处理onOpen、onClose、onError
30
+   */
31
+  public constructor(url: string, readyStateCallback: ReadyStateCallback) {
32
+    this.listeners = new Map<number, (data: WebSocketResp) => void>();
33
+    this.requestHeader = '';
34
+    this.requestHeader = '';
35
+    this._maxPayload = 1024 * 1024;
36
+    this.url = url;
37
+    this.reconnectTimes = 0;
38
+    this.readyStateCallback = readyStateCallback;
39
+    this._enableLogger = false;
40
+    this.socket = this.connect();
41
+  }
42
+
43
+  /**
44
+   * 设置可以处理的数据包上限
45
+   * @param maxPayload 最多可以处理的数据包大小
46
+   */
47
+  public set maxPayload(maxPayload: number) {
48
+    this._maxPayload = maxPayload;
49
+  }
50
+
51
+  /**
52
+   * 获取可以处理的数据包大小
53
+   */
54
+  public get maxPayload(): number {
55
+    return this._maxPayload;
56
+  }
57
+
58
+  /**
59
+   * 设置是否允许显示运行日志
60
+   */
61
+  public set enableLogger(enableLogger: boolean) {
62
+    this._enableLogger = enableLogger;
63
+  }
64
+
65
+  /**
66
+   * 获取是否显示日志的配置信息
67
+   */
68
+  public get enableLogger(): boolean {
69
+    return this._enableLogger;
70
+  }
71
+
72
+  /**
73
+   * 发送ping请求,来保持长连接
74
+   * @param param 请求参数,比如{"hello":"world"}
75
+   */
76
+  public async ping(param: object): Promise<WebSocketResp> {
77
+    return new Promise(
78
+      (
79
+        resolve: (data: WebSocketResp) => void,
80
+        reject: (err: WebsocketError) => void,
81
+      ): void => {
82
+        if (this.socket.readyState !== this.socket.OPEN) {
83
+          if (this._enableLogger) {
84
+            console.log('[ping]: connection refuse');
85
+          }
86
+
87
+          reject(new WebsocketError(clientError, 'connection refuse'));
88
+        }
89
+
90
+        const heartbeatOperator = 0;
91
+
92
+        this.listeners.set(
93
+          heartbeatOperator,
94
+          (data: WebSocketResp): void => {
95
+            const code = this.getResponseProperty('code');
96
+            if (code !== '') {
97
+              const message = this.getResponseProperty('message');
98
+              reject(new WebsocketError(Number(code), message));
99
+            } else {
100
+              resolve(data);
101
+            }
102
+          },
103
+        );
104
+
105
+        const p = new Packet();
106
+        this.send(
107
+          p.pack(
108
+            heartbeatOperator,
109
+            0,
110
+            this.requestHeader,
111
+            JSON.stringify(param),
112
+          ),
113
+        );
114
+
115
+        if (this._enableLogger) {
116
+          console.info(
117
+            '[send data packet]',
118
+            heartbeatOperator,
119
+            0,
120
+            this.requestHeader,
121
+            param,
122
+          );
123
+        }
124
+      },
125
+    );
126
+  }
127
+
128
+  /**
129
+   * 同步方式向服务端发送请求
130
+   * @param operator 路由地址
131
+   * @param param 请求参数,比如{"hello":"world"}
132
+   * @param callback 请求状态回调处理
133
+   */
134
+  public async request(
135
+    operator: string,
136
+    param: object,
137
+  ): Promise<WebSocketResp> {
138
+    return await this.asyncSend(operator, param);
139
+  }
140
+
141
+  /**
142
+   * 添加消息监听
143
+   * @description 添加消息监听器,比如operator是/v1/message/listener,那么从服务端推送到/v1/message/listener的消息会进入到定义的listener里面进行处理
144
+   * @param operator 消息监听地址
145
+   * @param listener 定义如何处理从服务端返回的消息
146
+   */
147
+  public addMessageListener(
148
+    operator: string,
149
+    listener: (data: WebSocketResp) => void,
150
+  ): void {
151
+    this.listeners.set(Utils.crc32(operator), listener);
152
+  }
153
+
154
+  /**
155
+   * 移除消息监听
156
+   * @param operator 消息监听地址
157
+   */
158
+  public removeMessageListener(operator: string): void {
159
+    delete this.listeners[Utils.crc32(operator)];
160
+  }
161
+
162
+  /**
163
+   * 返回Websocket链接状态
164
+   * @returns Websocket的链接状态
165
+   */
166
+  public get readyState(): number {
167
+    return this.socket.readyState;
168
+  }
169
+
170
+  /**
171
+   * 添加请求属性,会携带在数据帧里面发送到服务端
172
+   * @param key 属性名
173
+   * @param value 属性值
174
+   */
175
+  public setRequestProperty(key: string, value: string): void {
176
+    let v = this.getRequestProperty(key);
177
+
178
+    this.requestHeader = this.requestHeader.replace(key + '=' + v + ';', '');
179
+    this.requestHeader = this.requestHeader + key + '=' + value + ';';
180
+  }
181
+
182
+  /**
183
+   * 获取请求属性
184
+   * @param key 属性名
185
+   */
186
+  public getRequestProperty(key: string): string {
187
+    if (this.requestHeader !== undefined) {
188
+      let values = this.requestHeader.split(';');
189
+      for (let index in values) {
190
+        let kv = values[index].split('=');
191
+        if (kv[0] === key) {
192
+          return kv[1];
193
+        }
194
+      }
195
+    }
196
+
197
+    return '';
198
+  }
199
+
200
+  /**
201
+   * 设置响应属性,客户端基本用不到,都是服务端来进行设置
202
+   * @param key 属性名
203
+   * @param value 属性值
204
+   */
205
+  public setResponseProperty(key: string, value: string): void {
206
+    let v = this.getResponseProperty(key);
207
+
208
+    this.responseHeader = this.responseHeader.replace(key + '=' + v + ';', '');
209
+    this.responseHeader = this.responseHeader + key + '=' + value + ';';
210
+  }
211
+
212
+  /**
213
+   * 获取从服务端返回的属性
214
+   * @param key 获取响应属性
215
+   */
216
+  public getResponseProperty(key: string): string {
217
+    if (this.responseHeader !== undefined) {
218
+      let values = this.responseHeader.split(';');
219
+      for (let index in values) {
220
+        let kv = values[index].split('=');
221
+        if (kv[0] === key) {
222
+          return kv[1];
223
+        }
224
+      }
225
+    }
226
+
227
+    return '';
228
+  }
229
+  /**
230
+   * 关闭客户端链接
231
+   */
232
+  public close(code?: number, reason?: string): void {
233
+    this.socket.close(code, reason);
234
+  }
235
+  /**
236
+   * 创建websocket链接
237
+   */
238
+  private connect(): WebSocket {
239
+    const readyStateCallback = this.readyStateCallback;
240
+    let ws = new WebSocket(this.url);
241
+
242
+    ws.binaryType = 'blob';
243
+
244
+    ws.onopen = (ev): void => {
245
+      if (this._enableLogger) {
246
+        console.info('[websocket] open connection');
247
+      }
248
+
249
+      this.reconnectTimes = 0;
250
+
251
+      readyStateCallback.onOpen(ev);
252
+    };
253
+
254
+    ws.onclose = (ev): void => {
255
+      if (this._enableLogger) {
256
+        console.info('[websocket] close connection');
257
+      }
258
+
259
+      this.reconnect();
260
+
261
+      readyStateCallback.onClose(ev);
262
+    };
263
+
264
+    ws.onerror = (ev): void => {
265
+      if (this._enableLogger) {
266
+        console.info('[websocket] error');
267
+      }
268
+
269
+      this.reconnect();
270
+
271
+      readyStateCallback.onError(ev);
272
+    };
273
+
274
+    ws.onmessage = (ev): void => {
275
+      if (ev.data instanceof Blob) {
276
+        let reader = new FileReader();
277
+        reader.readAsArrayBuffer(ev.data);
278
+        reader.onload = (): void => {
279
+          try {
280
+            let packet = new Packet().unPack(reader.result as ArrayBuffer);
281
+            let packetLength = packet.headerLength + packet.bodyLength + 20;
282
+            if (packetLength > this._maxPayload) {
283
+              throw new Error('the packet is big than ' + this._maxPayload);
284
+            }
285
+
286
+            let operator = Number(packet.operator) + Number(packet.sequence);
287
+            if (this.listeners.has(operator)) {
288
+              if (packet.body === '') {
289
+                packet.body = '{}';
290
+              }
291
+
292
+              this.responseHeader = packet.header;
293
+
294
+              (this.listeners.get(operator) as (data: WebSocketResp) => void)(
295
+                JSON.parse(packet.body),
296
+              );
297
+            }
298
+
299
+            if (this._enableLogger) {
300
+              if (operator !== 0 && packet.body !== 'null') {
301
+                console.info('receive data packet', packet.body);
302
+              }
303
+            }
304
+          } catch (e) {
305
+            throw new Error(e);
306
+          }
307
+        };
308
+      } else {
309
+        throw new Error('unsupported data format');
310
+      }
311
+    };
312
+
313
+    return ws;
314
+  }
315
+
316
+  /**
317
+   * 断线重连
318
+   */
319
+  private reconnect(): void {
320
+    if (!this.reconnectLock) {
321
+      this.reconnectLock = true;
322
+      if (this._enableLogger) {
323
+        console.info('websocket reconnect in ' + this.reconnectTimes + 's');
324
+      }
325
+
326
+      // 尝试重连
327
+      setTimeout((): void => {
328
+        this.reconnectTimes++;
329
+        this.socket = this.connect();
330
+        this.reconnectLock = false;
331
+      }, this.reconnectTimes * 1000);
332
+    }
333
+  }
334
+
335
+  /**
336
+   * 向服务端发送数据请求
337
+   * @param data 向服务端传送的数据
338
+   */
339
+  private send(data: ArrayBuffer): void {
340
+    if (this.socket.readyState !== this.socket.OPEN) {
341
+      if (this._enableLogger) {
342
+        console.error(
343
+          '[send] WebSocket is already in CLOSING or CLOSED state.',
344
+        );
345
+      }
346
+
347
+      return;
348
+    }
349
+
350
+    try {
351
+      this.socket.send(data);
352
+    } catch (e) {
353
+      throw new Error('send data error' + e);
354
+    }
355
+  }
356
+
357
+  /**
358
+   * 异步向服务端发送请求
359
+   * @param operator 路由地址
360
+   * @param param 请求参数,比如{"hello":"world"}
361
+   * @param callback 请求状态回调处理
362
+   */
363
+  private asyncSend(operator: string, param: object): Promise<WebSocketResp> {
364
+    return new Promise(
365
+      (
366
+        resolve: (data: WebSocketResp) => void,
367
+        reject: (err: WebsocketError) => void,
368
+      ): void => {
369
+        if (this.socket.readyState !== this.socket.OPEN) {
370
+          if (this._enableLogger) {
371
+            console.log('[ping]: connection refuse');
372
+          }
373
+
374
+          reject(
375
+            new WebsocketError(clientError, 'asyncSend: connection refuse'),
376
+          );
377
+        }
378
+
379
+        const sequence = new Date().getTime();
380
+        const listener = Utils.crc32(operator) + sequence;
381
+        this.listeners.set(
382
+          listener,
383
+          (data: WebSocketResp): void => {
384
+            const code = this.getResponseProperty('code');
385
+            if (code !== '') {
386
+              const message = this.getResponseProperty('message');
387
+              reject(new WebsocketError(Number(code), message));
388
+            } else {
389
+              resolve(data);
390
+            }
391
+
392
+            delete this.listeners[listener];
393
+          },
394
+        );
395
+
396
+        const p = new Packet();
397
+        this.send(
398
+          p.pack(
399
+            Utils.crc32(operator),
400
+            sequence,
401
+            this.requestHeader,
402
+            JSON.stringify(param),
403
+          ),
404
+        );
405
+
406
+        if (this._enableLogger) {
407
+          console.info(
408
+            '[send data packet]',
409
+            operator,
410
+            sequence,
411
+            this.requestHeader,
412
+            param,
413
+          );
414
+        }
415
+      },
416
+    );
417
+  }
418
+}
419
+
420
+let client: Client;
421
+
422
+function getClient(url: string, callback: ReadyStateCallback): Client {
423
+  if (!client) {
424
+    client = new Client(url, callback);
425
+  }
426
+
427
+  return client;
428
+}
429
+
430
+export { Client, getClient };

src/error.ts → src/types/index.ts Ver arquivo

@@ -1,3 +1,7 @@
1
+export interface WebSocketResp {
2
+  value: object | string;
3
+}
4
+
1 5
 export class WebsocketError {
2 6
   private _code: number;
3 7
   private _msg: string;
@@ -24,3 +28,5 @@ export class WebsocketError {
24 28
     return this._msg;
25 29
   }
26 30
 }
31
+
32
+export { ReadyStateCallback } from './callback';