Browse Source

chore: update ts-sdk

wxyyxc1992 5 years ago
parent
commit
a6c28c9a2f
3 changed files with 229 additions and 146 deletions
  1. 36
    53
      packages/cts-core/example/index.ts
  2. 167
    93
      packages/cts-core/src/client.ts
  3. 26
    0
      packages/cts-core/src/error.ts

+ 36
- 53
packages/cts-core/example/index.ts View File

1
 import { Client } from '../src/client';
1
 import { Client } from '../src/client';
2
+import { WebsocketError } from './error';
2
 
3
 
3
 const url = 'ws://127.0.0.1:8081';
4
 const url = 'ws://127.0.0.1:8081';
4
-const client = new Client(
5
-  url,
6
-  new (class {
7
-    public onOpen(): void {
8
-      client.ping(
9
-        {},
10
-        new (class {
11
-          public onStart(): void {
12
-            console.log('start ping');
13
-          }
14
-
15
-          public onSuccess(data: string): void {
16
-            console.log('ping successful:', data);
17
-          }
18
-
19
-          public onError(code: number, message: string): void {
20
-            console.log('ping error:', message);
21
-          }
22
-
23
-          public onEnd(): void {
24
-            console.log('end ping');
25
-          }
26
-        })()
5
+const client = new Client(url, {
6
+  onOpen(): void {
7
+    client
8
+      .ping({})
9
+      .then(
10
+        (res: string): void => {
11
+          console.log('ping sucessful:', res);
12
+        },
13
+      )
14
+      .catch(
15
+        (reason: WebsocketError): void => {
16
+          console.log('ping error:', reason.code, reason.msg);
17
+        },
27
       );
18
       );
28
 
19
 
29
-      client.syncSend(
30
-        '/v1/healthy',
31
-        {},
32
-        new (class {
33
-          public onStart(): void {
34
-            console.log('start request');
35
-          }
36
-
37
-          public onSuccess(data: string): void {
38
-            console.log('request successful:', data);
39
-          }
40
-
41
-          public onError(code: number, message: string): void {
42
-            console.log('request error:', message);
43
-          }
44
-
45
-          public onEnd(): void {
46
-            console.log('end request');
47
-          }
48
-        })()
20
+    client
21
+      .request('/v1/healthy', {})
22
+      .then(
23
+        (res: string): void => {
24
+          console.log('request successful:', res);
25
+        },
26
+      )
27
+      .catch(
28
+        (reason: WebsocketError): void => {
29
+          console.log('request error:', reason.code, reason.msg);
30
+        },
49
       );
31
       );
50
-    }
32
+  },
33
+
34
+  onClose(ev: Event): void {
35
+    console.log('connection error', ev);
36
+    console.log(ev);
37
+  },
51
 
38
 
52
-    public onClose(ev: Event): void {
53
-      console.log('connection error', ev);
54
-      console.log(ev);
55
-    }
39
+  onError(): void {
40
+    console.log('close connection');
41
+  },
42
+});
56
 
43
 
57
-    public onError(): void {
58
-      console.log('close connection');
59
-    }
60
-  })()
61
-);
44
+client.enableLogger = true;

+ 167
- 93
packages/cts-core/src/client.ts View File

1
 import { Packet } from './packet';
1
 import { Packet } from './packet';
2
 import { Utils } from './utils';
2
 import { Utils } from './utils';
3
-import { ReadyStateCallback, RequestCallback } from './types/callback';
3
+import { ReadyStateCallback } from './types/callback';
4
+import { WebsocketError } from './error';
5
+
6
+const clientError = 400;
4
 
7
 
5
 /**
8
 /**
6
  * 初始化链接以及收发数据
9
  * 初始化链接以及收发数据
7
  */
10
  */
8
 class Client {
11
 class Client {
9
   private _maxPayload: number;
12
   private _maxPayload: number;
13
+  private _enableLogger: boolean;
10
   private listeners: Map<number, (data: string) => void>;
14
   private listeners: Map<number, (data: string) => void>;
11
   private requestHeader: string;
15
   private requestHeader: string;
12
   private responseHeader: string;
16
   private responseHeader: string;
29
     this.url = url;
33
     this.url = url;
30
     this.reconnectTimes = 0;
34
     this.reconnectTimes = 0;
31
     this.readyStateCallback = readyStateCallback;
35
     this.readyStateCallback = readyStateCallback;
36
+    this._enableLogger = false;
32
     this.socket = this.connect();
37
     this.socket = this.connect();
33
   }
38
   }
34
 
39
 
35
   /**
40
   /**
36
-   * 发送ping请求,来保持长连接
37
-   * @param param 请求参数,比如{"hello":"world"}
38
-   * @param requestCallback 请求状态回调
41
+   * 设置可以处理的数据包上限
42
+   * @param maxPayload 最多可以处理的数据包大小
39
    */
43
    */
40
-  public ping(param: object, requestCallback: RequestCallback): void {
41
-    if (this.socket.readyState !== this.socket.OPEN) {
42
-      throw new Error('asyncSend: connection refuse');
43
-    }
44
-
45
-    const heartbeatOperator = 0;
46
-
47
-    this.listeners.set(
48
-      heartbeatOperator,
49
-      (data: string): void => {
50
-        const code = this.getResponseProperty('code');
51
-        if (code !== '') {
52
-          const message = this.getResponseProperty('message');
53
-          requestCallback.onError(Number(code), message);
54
-        } else {
55
-          requestCallback.onSuccess(data);
56
-        }
44
+  public set maxPayload(maxPayload: number) {
45
+    this._maxPayload = maxPayload;
46
+  }
57
 
47
 
58
-        requestCallback.onEnd();
59
-      },
60
-    );
48
+  /**
49
+   * 获取可以处理的数据包大小
50
+   */
51
+  public get maxPayload(): number {
52
+    return this._maxPayload;
53
+  }
61
 
54
 
62
-    const p = new Packet();
63
-    this.send(
64
-      p.pack(heartbeatOperator, 0, this.requestHeader, JSON.stringify(param)),
65
-    );
55
+  /**
56
+   * 设置是否允许显示运行日志
57
+   */
58
+  public set enableLogger(enableLogger: boolean) {
59
+    this._enableLogger = enableLogger;
66
   }
60
   }
67
 
61
 
68
   /**
62
   /**
69
-   * 异步向服务端发送请求
70
-   * @param operator 路由地址
71
-   * @param param 请求参数,比如{"hello":"world"}
72
-   * @param callback 请求状态回调处理
63
+   * 获取是否显示日志的配置信息
73
    */
64
    */
74
-  public asyncSend(
75
-    operator: string,
76
-    param: object,
77
-    callback: RequestCallback,
78
-  ): void {
79
-    console.info('websocket send data', operator, this.requestHeader, param);
65
+  public get enableLogger(): boolean {
66
+    return this._enableLogger;
67
+  }
80
 
68
 
81
-    if (this.socket.readyState !== this.socket.OPEN) {
82
-      throw new Error('asyncSend: connection refuse');
83
-    }
69
+  /**
70
+   * 发送ping请求,来保持长连接
71
+   * @param param 请求参数,比如{"hello":"world"}
72
+   */
73
+  public async ping(param: object): Promise<string> {
74
+    return new Promise(
75
+      (
76
+        resolve: (data: string) => void,
77
+        reject: (err: WebsocketError) => void,
78
+      ): void => {
79
+        if (this.socket.readyState !== this.socket.OPEN) {
80
+          if (this._enableLogger) {
81
+            console.log('[ping]: connection refuse');
82
+          }
84
 
83
 
85
-    callback.onStart();
86
-
87
-    const sequence = new Date().getTime();
88
-    const listener = Utils.crc32(operator) + sequence;
89
-    this.listeners.set(
90
-      listener,
91
-      (data: string): void => {
92
-        const code = this.getResponseProperty('code');
93
-        if (code !== '') {
94
-          const message = this.getResponseProperty('message');
95
-          callback.onError(Number(code), message);
96
-        } else {
97
-          callback.onSuccess(data);
84
+          reject(new WebsocketError(clientError, 'connection refuse'));
98
         }
85
         }
99
 
86
 
100
-        callback.onEnd();
101
-
102
-        delete this.listeners[listener];
87
+        const heartbeatOperator = 0;
88
+
89
+        this.listeners.set(
90
+          heartbeatOperator,
91
+          (data: string): void => {
92
+            const code = this.getResponseProperty('code');
93
+            if (code !== '') {
94
+              const message = this.getResponseProperty('message');
95
+              reject(new WebsocketError(Number(code), message));
96
+            } else {
97
+              resolve(data);
98
+            }
99
+          },
100
+        );
101
+
102
+        const p = new Packet();
103
+        this.send(
104
+          p.pack(
105
+            heartbeatOperator,
106
+            0,
107
+            this.requestHeader,
108
+            JSON.stringify(param),
109
+          ),
110
+        );
111
+
112
+        if (this._enableLogger) {
113
+          console.info(
114
+            '[send data packet]',
115
+            heartbeatOperator,
116
+            0,
117
+            this.requestHeader,
118
+            param,
119
+          );
120
+        }
103
       },
121
       },
104
     );
122
     );
105
-
106
-    const p = new Packet();
107
-    this.send(
108
-      p.pack(
109
-        Utils.crc32(operator),
110
-        sequence,
111
-        this.requestHeader,
112
-        JSON.stringify(param),
113
-      ),
114
-    );
115
   }
123
   }
116
 
124
 
117
   /**
125
   /**
120
    * @param param 请求参数,比如{"hello":"world"}
128
    * @param param 请求参数,比如{"hello":"world"}
121
    * @param callback 请求状态回调处理
129
    * @param callback 请求状态回调处理
122
    */
130
    */
123
-  public async syncSend(
124
-    operator: string,
125
-    param: object,
126
-    callback: RequestCallback,
127
-  ): Promise<void> {
128
-    await this.asyncSend(operator, param, callback);
131
+  public async request(operator: string, param: object): Promise<string> {
132
+    return await this.asyncSend(operator, param);
129
   }
133
   }
130
 
134
 
131
   /**
135
   /**
157
     return this.socket.readyState;
161
     return this.socket.readyState;
158
   }
162
   }
159
 
163
 
160
-  /**
161
-   * 设置可以处理的数据包上限
162
-   * @param maxPayload 最多可以处理的数据包大小
163
-   */
164
-  public set maxPayload(maxPayload: number) {
165
-    this._maxPayload = maxPayload;
166
-  }
167
-
168
-  /**
169
-   * 获取可以处理的数据包大小
170
-   */
171
-  public get maxPayload(): number {
172
-    return this._maxPayload;
173
-  }
174
-
175
   /**
164
   /**
176
    * 添加请求属性,会携带在数据帧里面发送到服务端
165
    * 添加请求属性,会携带在数据帧里面发送到服务端
177
    * @param key 属性名
166
    * @param key 属性名
242
     ws.binaryType = 'blob';
231
     ws.binaryType = 'blob';
243
 
232
 
244
     ws.onopen = (ev): void => {
233
     ws.onopen = (ev): void => {
234
+      if (this._enableLogger) {
235
+        console.info('[websocket] open connection');
236
+      }
237
+
245
       this.reconnectTimes = 0;
238
       this.reconnectTimes = 0;
246
 
239
 
247
       readyStateCallback.onOpen(ev);
240
       readyStateCallback.onOpen(ev);
248
     };
241
     };
249
 
242
 
250
     ws.onclose = (ev): void => {
243
     ws.onclose = (ev): void => {
244
+      if (this._enableLogger) {
245
+        console.info('[websocket] close connection');
246
+      }
247
+
251
       this.reconnect();
248
       this.reconnect();
252
 
249
 
253
       readyStateCallback.onClose(ev);
250
       readyStateCallback.onClose(ev);
254
     };
251
     };
255
 
252
 
256
     ws.onerror = (ev): void => {
253
     ws.onerror = (ev): void => {
254
+      if (this._enableLogger) {
255
+        console.info('[websocket] error');
256
+      }
257
+
257
       this.reconnect();
258
       this.reconnect();
258
 
259
 
259
       readyStateCallback.onError(ev);
260
       readyStateCallback.onError(ev);
284
               );
285
               );
285
             }
286
             }
286
 
287
 
287
-            if (operator !== 0 && packet.body !== 'null') {
288
-              console.info('receive data', packet.body);
288
+            if (this._enableLogger) {
289
+              if (operator !== 0 && packet.body !== 'null') {
290
+                console.info('receive data packet', packet.body);
291
+              }
289
             }
292
             }
290
           } catch (e) {
293
           } catch (e) {
291
             throw new Error(e);
294
             throw new Error(e);
305
   private reconnect(): void {
308
   private reconnect(): void {
306
     if (!this.reconnectLock) {
309
     if (!this.reconnectLock) {
307
       this.reconnectLock = true;
310
       this.reconnectLock = true;
308
-      console.info('websocket reconnect in ' + this.reconnectTimes + 's');
311
+      if (this._enableLogger) {
312
+        console.info('websocket reconnect in ' + this.reconnectTimes + 's');
313
+      }
314
+
309
       // 尝试重连
315
       // 尝试重连
310
       setTimeout((): void => {
316
       setTimeout((): void => {
311
         this.reconnectTimes++;
317
         this.reconnectTimes++;
321
    */
327
    */
322
   private send(data: ArrayBuffer): void {
328
   private send(data: ArrayBuffer): void {
323
     if (this.socket.readyState !== this.socket.OPEN) {
329
     if (this.socket.readyState !== this.socket.OPEN) {
324
-      console.error('WebSocket is already in CLOSING or CLOSED state.');
330
+      if (this._enableLogger) {
331
+        console.error(
332
+          '[send] WebSocket is already in CLOSING or CLOSED state.',
333
+        );
334
+      }
335
+
325
       return;
336
       return;
326
     }
337
     }
338
+
327
     try {
339
     try {
328
       this.socket.send(data);
340
       this.socket.send(data);
329
     } catch (e) {
341
     } catch (e) {
330
-      console.log('send data error', e);
342
+      throw new Error('send data error' + e);
331
     }
343
     }
332
   }
344
   }
345
+
346
+  /**
347
+   * 异步向服务端发送请求
348
+   * @param operator 路由地址
349
+   * @param param 请求参数,比如{"hello":"world"}
350
+   * @param callback 请求状态回调处理
351
+   */
352
+  private asyncSend(operator: string, param: object): Promise<string> {
353
+    return new Promise(
354
+      (
355
+        resolve: (data: string) => void,
356
+        reject: (err: WebsocketError) => void,
357
+      ): void => {
358
+        if (this.socket.readyState !== this.socket.OPEN) {
359
+          if (this._enableLogger) {
360
+            console.log('[ping]: connection refuse');
361
+          }
362
+
363
+          reject(
364
+            new WebsocketError(clientError, 'asyncSend: connection refuse'),
365
+          );
366
+        }
367
+
368
+        const sequence = new Date().getTime();
369
+        const listener = Utils.crc32(operator) + sequence;
370
+        this.listeners.set(
371
+          listener,
372
+          (data: string): void => {
373
+            const code = this.getResponseProperty('code');
374
+            if (code !== '') {
375
+              const message = this.getResponseProperty('message');
376
+              reject(new WebsocketError(Number(code), message));
377
+            } else {
378
+              resolve(data);
379
+            }
380
+
381
+            delete this.listeners[listener];
382
+          },
383
+        );
384
+
385
+        const p = new Packet();
386
+        this.send(
387
+          p.pack(
388
+            Utils.crc32(operator),
389
+            sequence,
390
+            this.requestHeader,
391
+            JSON.stringify(param),
392
+          ),
393
+        );
394
+
395
+        if (this._enableLogger) {
396
+          console.info(
397
+            '[send data packet]',
398
+            operator,
399
+            sequence,
400
+            this.requestHeader,
401
+            param,
402
+          );
403
+        }
404
+      },
405
+    );
406
+  }
333
 }
407
 }
334
 
408
 
335
 export { Client };
409
 export { Client };

+ 26
- 0
packages/cts-core/src/error.ts View File

1
+export class WebsocketError {
2
+  private _code: number;
3
+  private _msg: string;
4
+
5
+  /**
6
+   * 构造函数
7
+   */
8
+  public constructor(code: number, msg: string) {
9
+    this._code = code;
10
+    this._msg = msg;
11
+  }
12
+
13
+  /**
14
+   * 返回错误码
15
+   */
16
+  public get code(): number {
17
+    return this._code;
18
+  }
19
+
20
+  /**
21
+   * 返回具体的错误信息
22
+   */
23
+  public get msg(): string {
24
+    return this._msg;
25
+  }
26
+}