Bladeren bron

add all file from old js

Paul 5 jaren geleden
bovenliggende
commit
c72da8f193
12 gewijzigde bestanden met toevoegingen van 653 en 44 verwijderingen
  1. 3
    0
      dist/callback.js
  2. 1
    0
      dist/callback.js.map
  3. 283
    0
      dist/index.js
  4. 1
    0
      dist/index.js.map
  5. 14
    14
      dist/packet.js
  6. 1
    1
      dist/packet.js.map
  7. 11
    0
      dist/types/callback.d.ts
  8. 1
    0
      dist/types/index.d.ts
  9. 9
    9
      dist/types/packet.d.ts
  10. 12
    0
      src/callback.ts
  11. 297
    0
      src/index.ts
  12. 20
    20
      src/packet.ts

+ 3
- 0
dist/callback.js Bestand weergeven

@@ -0,0 +1,3 @@
1
+"use strict";
2
+exports.__esModule = true;
3
+//# sourceMappingURL=callback.js.map

+ 1
- 0
dist/callback.js.map Bestand weergeven

@@ -0,0 +1 @@
1
+{"version":3,"file":"callback.js","sourceRoot":"","sources":["../src/callback.ts"],"names":[],"mappings":""}

+ 283
- 0
dist/index.js Bestand weergeven

@@ -0,0 +1,283 @@
1
+"use strict";
2
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+    return new (P || (P = Promise))(function (resolve, reject) {
4
+        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
7
+        step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+    });
9
+};
10
+var __generator = (this && this.__generator) || function (thisArg, body) {
11
+    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12
+    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
+    function verb(n) { return function (v) { return step([n, v]); }; }
14
+    function step(op) {
15
+        if (f) throw new TypeError("Generator is already executing.");
16
+        while (_) try {
17
+            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
+            if (y = 0, t) op = [op[0] & 2, t.value];
19
+            switch (op[0]) {
20
+                case 0: case 1: t = op; break;
21
+                case 4: _.label++; return { value: op[1], done: false };
22
+                case 5: _.label++; y = op[1]; op = [0]; continue;
23
+                case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
+                default:
25
+                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
+                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
+                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
+                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
+                    if (t[2]) _.ops.pop();
30
+                    _.trys.pop(); continue;
31
+            }
32
+            op = body.call(thisArg, _);
33
+        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
+        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
+    }
36
+};
37
+exports.__esModule = true;
38
+var constant = require("./constant");
39
+var packet_1 = require("./packet");
40
+var utils_1 = require("./utils");
41
+/**
42
+ * Client ws client, 单例模式, 负责维护连接
43
+ */
44
+var Client = /** @class */ (function () {
45
+    function Client(url, readyStateCallback) {
46
+        if (!('WebSocket' in window)) {
47
+            return;
48
+        }
49
+        this.requestHeader = '';
50
+        this.maxPayload = constant.MAX_PAYLOAD;
51
+        this.url = url;
52
+        this.readyStateCallback = readyStateCallback;
53
+        this.reconnectTimes = 0;
54
+        this.reconnectLock = false;
55
+        this.socket = this.connect();
56
+    }
57
+    // 向服务端发送ping包保持长连接
58
+    Client.prototype.ping = function (param, callback) {
59
+        if (param === void 0) { param = {}; }
60
+        if (callback === void 0) { callback = {}; }
61
+        if (typeof callback !== 'object') {
62
+            throw new Error('callback must be an object');
63
+        }
64
+        if (this.socket.readyState !== this.socket.OPEN) {
65
+            throw new Error('asyncSend: connection refuse');
66
+        }
67
+        var _this = this;
68
+        this.addMessageListener(0, function (data) {
69
+            var code = _this.getResponseProperty('code');
70
+            if (typeof code !== 'undefined') {
71
+                var message = _this.getResponseProperty('message');
72
+                if (this.callback.onError !== null) {
73
+                    this.callback.onError(code, message);
74
+                }
75
+            }
76
+            else {
77
+                this.callback.onSuccess(data);
78
+            }
79
+            this.callback.onEnd();
80
+        });
81
+        var p = new packet_1.Packet();
82
+        _this.send(p.pack(0, 0, _this.requestHeader, JSON.stringify(param)));
83
+    };
84
+    Client.prototype.send = function (data) {
85
+        if (this.socket.readyState !== this.socket.OPEN) {
86
+            console.error('WebSocket is already in CLOSING or CLOSED state.');
87
+            return;
88
+        }
89
+        try {
90
+            this.socket.send(data);
91
+        }
92
+        catch (e) {
93
+            console.log('send data error', e);
94
+        }
95
+    };
96
+    /**
97
+     * asyncSend
98
+     * @param {*} operator
99
+     * @param {*} param
100
+     * @param {*} callback 仅此次有效的callback
101
+     */
102
+    Client.prototype.asyncSend = function (operator, param, callback) {
103
+        console.info('websocket send data', operator, this.requestHeader, param);
104
+        if (typeof callback !== 'object') {
105
+            throw new Error('callback must be an object');
106
+        }
107
+        if (this.socket.readyState !== this.socket.OPEN) {
108
+            throw new Error('asyncSend: connection refuse');
109
+        }
110
+        if (callback.hasOwnProperty('onStart') &&
111
+            typeof callback.onStart === 'function') {
112
+            callback.onStart();
113
+        }
114
+        var _this = this;
115
+        var sequence = new Date().getTime();
116
+        var listener = utils_1.Utils.crc32(operator) + sequence;
117
+        this.callback[listener] = function (data) {
118
+            var code = _this.getResponseProperty('code');
119
+            if (typeof code !== 'undefined') {
120
+                var message = _this.getResponseProperty('message');
121
+                if (callback.hasOwnProperty('onError') &&
122
+                    typeof callback.onError === 'function') {
123
+                    callback.onError(code, message);
124
+                }
125
+            }
126
+            else {
127
+                if (callback.hasOwnProperty('onSuccess') &&
128
+                    typeof callback.onSuccess === 'function') {
129
+                    callback.onSuccess(data);
130
+                }
131
+            }
132
+            if (callback.hasOwnProperty('onEnd') &&
133
+                typeof callback.onEnd === 'function') {
134
+                callback.onEnd();
135
+            }
136
+            delete _this.callback[listener];
137
+        };
138
+        var p = new packet_1.Packet();
139
+        this.send(p.pack(utils_1.Utils.crc32(operator), sequence, this.requestHeader, JSON.stringify(param)));
140
+    };
141
+    // 同步请求服务端数据
142
+    Client.prototype.syncSend = function (operator, param, callback) {
143
+        return __awaiter(this, void 0, void 0, function () {
144
+            return __generator(this, function (_a) {
145
+                switch (_a.label) {
146
+                    case 0: return [4 /*yield*/, this.asyncSend(operator, param, callback)];
147
+                    case 1:
148
+                        _a.sent();
149
+                        return [2 /*return*/];
150
+                }
151
+            });
152
+        });
153
+    };
154
+    // 添加消息监听
155
+    Client.prototype.addMessageListener = function (operator, listener) {
156
+        this.callback[utils_1.Utils.crc32(operator)] = listener;
157
+    };
158
+    // 移除消息监听
159
+    Client.prototype.removeMessageListener = function (operator) {
160
+        delete this.callback[utils_1.Utils.crc32(operator)];
161
+    };
162
+    // 获取socket的链接状态
163
+    Client.prototype.getReadyState = function () {
164
+        return this.socket.readyState;
165
+    };
166
+    // 设置单个请求能够处理的最大字节数
167
+    Client.prototype.setMaxPayload = function (maxPayload) {
168
+        this.maxPayload = maxPayload;
169
+    };
170
+    // 设置请求属性
171
+    Client.prototype.setRequestProperty = function (key, value) {
172
+        var v = this.getRequestProperty(key);
173
+        this.requestHeader = this.requestHeader.replace(key + '=' + v + ';', '');
174
+        this.requestHeader = this.requestHeader + key + '=' + value + ';';
175
+    };
176
+    // 获取请求属性
177
+    Client.prototype.getRequestProperty = function (key) {
178
+        var values = this.requestHeader.split(';');
179
+        for (var index in values) {
180
+            var kv = values[index].split('=');
181
+            if (kv[0] === key) {
182
+                return kv[1];
183
+            }
184
+        }
185
+    };
186
+    // 设置Response属性
187
+    Client.prototype.setResponseProperty = function (key, value) {
188
+        var v = this.getResponseProperty(key);
189
+        this.responseHeader = this.responseHeader.replace(key + '=' + v + ';', '');
190
+        this.responseHeader = this.responseHeader + key + '=' + value + ';';
191
+    };
192
+    // 获取响应属性
193
+    Client.prototype.getResponseProperty = function (key) {
194
+        var values = this.responseHeader.split(';');
195
+        for (var index in values) {
196
+            var kv = values[index].split('=');
197
+            if (kv[0] === key) {
198
+                return kv[1];
199
+            }
200
+        }
201
+    };
202
+    // 创建连接
203
+    Client.prototype.connect = function () {
204
+        var url = this.url;
205
+        var readyStateCallback = this.readyStateCallback;
206
+        var ws = new WebSocket(url);
207
+        var _this = this;
208
+        ws.binaryType = 'blob';
209
+        ws.onopen = function (ev) {
210
+            console.info('websocket connected');
211
+            _this.reconnectTimes = 0;
212
+            if (readyStateCallback.hasOwnProperty('onopen') &&
213
+                typeof readyStateCallback.onopen === 'function') {
214
+                readyStateCallback.onopen(ev);
215
+            }
216
+        };
217
+        ws.onclose = function (ev) {
218
+            console.info('websocket disconnected');
219
+            _this.reconnect();
220
+            if (readyStateCallback.hasOwnProperty('onclose') &&
221
+                typeof readyStateCallback.onclose === 'function') {
222
+                readyStateCallback.onclose(ev);
223
+            }
224
+        };
225
+        ws.onerror = function (ev) {
226
+            console.info('websocket error disconnected');
227
+            _this.reconnect();
228
+            if (readyStateCallback.hasOwnProperty('onerror') &&
229
+                typeof readyStateCallback.onerror === 'function') {
230
+                readyStateCallback.onerror(ev);
231
+            }
232
+        };
233
+        ws.onmessage = function (ev) {
234
+            if (ev.data instanceof Blob) {
235
+                var reader = new FileReader();
236
+                reader.readAsArrayBuffer(ev.data);
237
+                reader.onload = function () {
238
+                    try {
239
+                        var packet = new packet_1.Packet().unPack(this.result);
240
+                        var packetLength = packet.headerLength + packet.bodyLength + 20;
241
+                        if (packetLength > constant.MAX_PAYLOAD) {
242
+                            throw new Error('the packet is big than ' + constant.MAX_PAYLOAD);
243
+                        }
244
+                        var operator = Number(packet.operator) + Number(packet.sequence);
245
+                        if (_this.callback.hasOwnProperty(operator)) {
246
+                            if (packet.body === '') {
247
+                                packet.body = '{}';
248
+                            }
249
+                            _this.responseHeader = packet.header;
250
+                            _this.callback[operator](JSON.parse(packet.body));
251
+                        }
252
+                        if (operator !== 0 && packet.body !== 'null') {
253
+                            console.info('receive data', packet.body);
254
+                        }
255
+                    }
256
+                    catch (e) {
257
+                        console.info(e);
258
+                        throw new Error(e);
259
+                    }
260
+                };
261
+            }
262
+            else {
263
+                throw new Error('websocket unsupported data format');
264
+            }
265
+        };
266
+        return ws;
267
+    };
268
+    Client.prototype.reconnect = function () {
269
+        var _this_1 = this;
270
+        if (!this.reconnectLock) {
271
+            this.reconnectLock = true;
272
+            console.info('websocket reconnect in ' + this.reconnectTimes + 's');
273
+            // 尝试重连
274
+            setTimeout(function () {
275
+                _this_1.reconnectTimes++;
276
+                _this_1.socket = _this_1.connect();
277
+                _this_1.reconnectLock = false;
278
+            }, this.reconnectTimes * 1000);
279
+        }
280
+    };
281
+    return Client;
282
+}());
283
+//# sourceMappingURL=index.js.map

+ 1
- 0
dist/index.js.map
Diff onderdrukt omdat het te groot bestand
Bestand weergeven


+ 14
- 14
dist/packet.js Bestand weergeven

@@ -4,10 +4,11 @@ var utils_1 = require("./utils");
4 4
 var Int64 = require("node-int64");
5 5
 var Packet = /** @class */ (function () {
6 6
     function Packet() {
7
+        this.key = 'b8ca9aa66def05ff3f24919274bb4a66';
7 8
     }
8
-    Packet.pack = function (operator, sequence, header, body) {
9
-        var header = utils_1.Utils.encrypt(header, Packet.key, Packet.key);
10
-        var body = utils_1.Utils.encrypt(body, Packet.key, Packet.key);
9
+    Packet.prototype.pack = function (operator, sequence, header, body) {
10
+        header = utils_1.Utils.encrypt(header, this.key, this.key);
11
+        body = utils_1.Utils.encrypt(body, this.key, this.key);
11 12
         var headerLength = header.length;
12 13
         var bodyLength = body.length;
13 14
         var buf = new ArrayBuffer(20 + headerLength + bodyLength);
@@ -28,19 +29,18 @@ var Packet = /** @class */ (function () {
28 29
         }
29 30
         return buf;
30 31
     };
31
-    Packet.unPack = function (data) {
32
+    Packet.prototype.unPack = function (data) {
32 33
         var dataView = new DataView(data);
33
-        Packet.operator = dataView.getUint32(0, false);
34
-        Packet.sequence = new Int64(new Uint8Array(dataView.buffer.slice(4, 12))).toNumber();
35
-        Packet.headerLength = dataView.getUint32(12, false);
36
-        Packet.bodyLength = dataView.getUint32(16, false);
37
-        var header = utils_1.Utils.ab2str(dataView.buffer.slice(20, 20 + Packet.headerLength));
38
-        var body = utils_1.Utils.ab2str(dataView.buffer.slice(20 + Packet.headerLength));
39
-        Packet.header = utils_1.Utils.decrypt(header, Packet.key, Packet.key);
40
-        Packet.body = utils_1.Utils.decrypt(body, Packet.key, Packet.key);
41
-        return Packet;
34
+        this.operator = dataView.getUint32(0, false);
35
+        this.sequence = new Int64(new Uint8Array(dataView.buffer.slice(4, 12))).toNumber();
36
+        this.headerLength = dataView.getUint32(12, false);
37
+        this.bodyLength = dataView.getUint32(16, false);
38
+        var header = utils_1.Utils.ab2str(dataView.buffer.slice(20, 20 + this.headerLength));
39
+        var body = utils_1.Utils.ab2str(dataView.buffer.slice(20 + this.headerLength));
40
+        this.header = utils_1.Utils.decrypt(header, this.key, this.key);
41
+        this.body = utils_1.Utils.decrypt(body, this.key, this.key);
42
+        return this;
42 43
     };
43
-    Packet.key = 'b8ca9aa66def05ff3f24919274bb4a66';
44 44
     return Packet;
45 45
 }());
46 46
 exports.Packet = Packet;

+ 1
- 1
dist/packet.js.map Bestand weergeven

@@ -1 +1 @@
1
-{"version":3,"file":"packet.js","sourceRoot":"","sources":["../src/packet.ts"],"names":[],"mappings":";;AAAA,iCAAgC;AAChC,kCAAoC;AAEpC;IAAA;IAgEA,CAAC;IAvDgB,WAAI,GAAnB,UACE,QAAgB,EAChB,QAAgB,EAChB,MAAc,EACd,IAAY;QAEZ,IAAM,MAAM,GAAG,aAAK,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,IAAM,IAAI,GAAG,aAAK,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;QAEzD,IAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC;QACnC,IAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;QAE/B,IAAM,GAAG,GAAG,IAAI,WAAW,CAAC,EAAE,GAAG,YAAY,GAAG,UAAU,CAAC,CAAC;QAC5D,IAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC;QACnC,IAAM,KAAK,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC;QAE7C,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;QACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QAEnC,IAAI,OAAO,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;QAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1B,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;SAC3B;QACD,KAAK,IAAI,GAAC,GAAG,CAAC,EAAE,GAAC,GAAG,YAAY,EAAE,GAAC,EAAE,EAAE;YACrC,OAAO,CAAC,EAAE,GAAG,GAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,GAAC,CAAC,CAAC;SACxC;QAED,KAAK,IAAI,GAAC,GAAG,CAAC,EAAE,GAAC,GAAG,UAAU,EAAE,GAAC,EAAE,EAAE;YACnC,OAAO,CAAC,EAAE,GAAG,YAAY,GAAG,GAAC,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,GAAC,CAAC,CAAC;SACrD;QAED,OAAO,GAAG,CAAC;IACb,CAAC;IAEc,aAAM,GAArB,UAAsB,IAAiB;QACrC,IAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEpC,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAC/C,MAAM,CAAC,QAAQ,GAAG,IAAI,KAAK,CACzB,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAC7C,CAAC,QAAQ,EAAE,CAAC;QACb,MAAM,CAAC,YAAY,GAAG,QAAQ,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QACpD,MAAM,CAAC,UAAU,GAAG,QAAQ,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAElD,IAAM,MAAM,GAAG,aAAK,CAAC,MAAM,CACzB,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC,CACpD,CAAC;QACF,IAAM,IAAI,GAAG,aAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;QAE3E,MAAM,CAAC,MAAM,GAAG,aAAK,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9D,MAAM,CAAC,IAAI,GAAG,aAAK,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;QAE1D,OAAO,MAAM,CAAC;IAChB,CAAC;IA9Dc,UAAG,GAAG,kCAAkC,CAAC;IA+D1D,aAAC;CAAA,AAhED,IAgEC;AAhEY,wBAAM"}
1
+{"version":3,"file":"packet.js","sourceRoot":"","sources":["../src/packet.ts"],"names":[],"mappings":"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"}

+ 11
- 0
dist/types/callback.d.ts Bestand weergeven

@@ -0,0 +1,11 @@
1
+export interface readyStateCallback {
2
+    onopen(ev: Event): any;
3
+    onerror(ev: Event): any;
4
+    onclose(ev: Event): any;
5
+}
6
+export interface callback {
7
+    onStart(): any;
8
+    onSuccess(data: string): any;
9
+    onError(code: number, message: string): any;
10
+    onEnd(): any;
11
+}

+ 1
- 0
dist/types/index.d.ts Bestand weergeven

@@ -0,0 +1 @@
1
+export {};

+ 9
- 9
dist/types/packet.d.ts Bestand weergeven

@@ -1,11 +1,11 @@
1 1
 export declare class Packet {
2
-    private static key;
3
-    private static operator;
4
-    private static sequence;
5
-    private static headerLength;
6
-    private static bodyLength;
7
-    private static header;
8
-    private static body;
9
-    private static pack;
10
-    private static unPack;
2
+    private key;
3
+    operator: number;
4
+    sequence: number;
5
+    headerLength: number;
6
+    bodyLength: number;
7
+    header: string;
8
+    body: string;
9
+    pack(operator: number, sequence: number, header: string, body: string): ArrayBuffer;
10
+    unPack(data: any): Packet;
11 11
 }

+ 12
- 0
src/callback.ts Bestand weergeven

@@ -0,0 +1,12 @@
1
+export interface readyStateCallback {
2
+  onopen(ev: Event);
3
+  onerror(ev: Event);
4
+  onclose(ev: Event);
5
+}
6
+
7
+export interface callback {
8
+  onStart();
9
+  onSuccess(data: string);
10
+  onError(code: number, message: string);
11
+  onEnd();
12
+}

+ 297
- 0
src/index.ts Bestand weergeven

@@ -0,0 +1,297 @@
1
+import * as constant from './constant';
2
+import { readyStateCallback, callback } from './callback';
3
+import { Packet } from './packet';
4
+import { Utils } from './utils';
5
+
6
+/**
7
+ * Client ws client, 单例模式, 负责维护连接
8
+ */
9
+class Client {
10
+  public callback: callback;
11
+  public requestHeader: string;
12
+  public responseHeader: string;
13
+  public maxPayload: number;
14
+  public url: string;
15
+  public reconnectTimes: number;
16
+  public reconnectLock: boolean;
17
+  public socket: WebSocket;
18
+  public readyStateCallback: readyStateCallback;
19
+
20
+  constructor(url: string, readyStateCallback: readyStateCallback) {
21
+    if (!('WebSocket' in window)) {
22
+      return;
23
+    }
24
+
25
+    this.requestHeader = '';
26
+    this.maxPayload = constant.MAX_PAYLOAD;
27
+    this.url = url;
28
+    this.readyStateCallback = readyStateCallback;
29
+    this.reconnectTimes = 0;
30
+    this.reconnectLock = false;
31
+
32
+    this.socket = this.connect();
33
+  }
34
+
35
+  // 向服务端发送ping包保持长连接
36
+  ping(param = {}, callback = {}) {
37
+    if (typeof callback !== 'object') {
38
+      throw new Error('callback must be an object');
39
+    }
40
+
41
+    if (this.socket.readyState !== this.socket.OPEN) {
42
+      throw new Error('asyncSend: connection refuse');
43
+    }
44
+
45
+    let _this = this;
46
+    this.addMessageListener(0, function(data) {
47
+      let code = _this.getResponseProperty('code');
48
+      if (typeof code !== 'undefined') {
49
+        let message = _this.getResponseProperty('message');
50
+        if (this.callback.onError !== null) {
51
+          this.callback.onError(code, message);
52
+        }
53
+      } else {
54
+        this.callback.onSuccess(data);
55
+      }
56
+
57
+      this.callback.onEnd();
58
+    });
59
+
60
+    const p = new Packet();
61
+    _this.send(p.pack(0, 0, _this.requestHeader, JSON.stringify(param)));
62
+  }
63
+
64
+  send(data) {
65
+    if (this.socket.readyState !== this.socket.OPEN) {
66
+      console.error('WebSocket is already in CLOSING or CLOSED state.');
67
+      return;
68
+    }
69
+    try {
70
+      this.socket.send(data);
71
+    } catch (e) {
72
+      console.log('send data error', e);
73
+    }
74
+  }
75
+
76
+  /**
77
+   * asyncSend
78
+   * @param {*} operator
79
+   * @param {*} param
80
+   * @param {*} callback 仅此次有效的callback
81
+   */
82
+  asyncSend(operator, param, callback) {
83
+    console.info('websocket send data', operator, this.requestHeader, param);
84
+
85
+    if (typeof callback !== 'object') {
86
+      throw new Error('callback must be an object');
87
+    }
88
+
89
+    if (this.socket.readyState !== this.socket.OPEN) {
90
+      throw new Error('asyncSend: connection refuse');
91
+    }
92
+
93
+    if (
94
+      callback.hasOwnProperty('onStart') &&
95
+      typeof callback.onStart === 'function'
96
+    ) {
97
+      callback.onStart();
98
+    }
99
+
100
+    let _this = this;
101
+    let sequence = new Date().getTime();
102
+    let listener = Utils.crc32(operator) + sequence;
103
+    this.callback[listener] = function(data) {
104
+      let code = _this.getResponseProperty('code');
105
+      if (typeof code !== 'undefined') {
106
+        let message = _this.getResponseProperty('message');
107
+        if (
108
+          callback.hasOwnProperty('onError') &&
109
+          typeof callback.onError === 'function'
110
+        ) {
111
+          callback.onError(code, message);
112
+        }
113
+      } else {
114
+        if (
115
+          callback.hasOwnProperty('onSuccess') &&
116
+          typeof callback.onSuccess === 'function'
117
+        ) {
118
+          callback.onSuccess(data);
119
+        }
120
+      }
121
+
122
+      if (
123
+        callback.hasOwnProperty('onEnd') &&
124
+        typeof callback.onEnd === 'function'
125
+      ) {
126
+        callback.onEnd();
127
+      }
128
+
129
+      delete _this.callback[listener];
130
+    };
131
+
132
+    const p = new Packet();
133
+    this.send(
134
+      p.pack(
135
+        Utils.crc32(operator),
136
+        sequence,
137
+        this.requestHeader,
138
+        JSON.stringify(param),
139
+      ),
140
+    );
141
+  }
142
+
143
+  // 同步请求服务端数据
144
+  async syncSend(operator, param, callback) {
145
+    await this.asyncSend(operator, param, callback);
146
+  }
147
+
148
+  // 添加消息监听
149
+  addMessageListener(operator, listener) {
150
+    this.callback[Utils.crc32(operator)] = listener;
151
+  }
152
+
153
+  // 移除消息监听
154
+  removeMessageListener(operator) {
155
+    delete this.callback[Utils.crc32(operator)];
156
+  }
157
+
158
+  // 获取socket的链接状态
159
+  getReadyState() {
160
+    return this.socket.readyState;
161
+  }
162
+
163
+  // 设置单个请求能够处理的最大字节数
164
+  setMaxPayload(maxPayload) {
165
+    this.maxPayload = maxPayload;
166
+  }
167
+
168
+  // 设置请求属性
169
+  setRequestProperty(key, value) {
170
+    let v = this.getRequestProperty(key);
171
+
172
+    this.requestHeader = this.requestHeader.replace(key + '=' + v + ';', '');
173
+    this.requestHeader = this.requestHeader + key + '=' + value + ';';
174
+  }
175
+
176
+  // 获取请求属性
177
+  getRequestProperty(key) {
178
+    let values = this.requestHeader.split(';');
179
+    for (let index in values) {
180
+      let kv = values[index].split('=');
181
+      if (kv[0] === key) {
182
+        return kv[1];
183
+      }
184
+    }
185
+  }
186
+
187
+  // 设置Response属性
188
+  setResponseProperty(key, value) {
189
+    let v = this.getResponseProperty(key);
190
+
191
+    this.responseHeader = this.responseHeader.replace(key + '=' + v + ';', '');
192
+    this.responseHeader = this.responseHeader + key + '=' + value + ';';
193
+  }
194
+
195
+  // 获取响应属性
196
+  getResponseProperty(key) {
197
+    let values = this.responseHeader.split(';');
198
+    for (let index in values) {
199
+      let kv = values[index].split('=');
200
+      if (kv[0] === key) {
201
+        return kv[1];
202
+      }
203
+    }
204
+  }
205
+
206
+  // 创建连接
207
+  connect() {
208
+    const url = this.url;
209
+    const readyStateCallback = this.readyStateCallback;
210
+
211
+    let ws = new WebSocket(url);
212
+    let _this = this;
213
+
214
+    ws.binaryType = 'blob';
215
+
216
+    ws.onopen = function(ev) {
217
+      console.info('websocket connected');
218
+      _this.reconnectTimes = 0;
219
+      if (
220
+        readyStateCallback.hasOwnProperty('onopen') &&
221
+        typeof readyStateCallback.onopen === 'function'
222
+      ) {
223
+        readyStateCallback.onopen(ev);
224
+      }
225
+    };
226
+
227
+    ws.onclose = function(ev) {
228
+      console.info('websocket disconnected');
229
+      _this.reconnect();
230
+      if (
231
+        readyStateCallback.hasOwnProperty('onclose') &&
232
+        typeof readyStateCallback.onclose === 'function'
233
+      ) {
234
+        readyStateCallback.onclose(ev);
235
+      }
236
+    };
237
+
238
+    ws.onerror = function(ev) {
239
+      console.info('websocket error disconnected');
240
+      _this.reconnect();
241
+      if (
242
+        readyStateCallback.hasOwnProperty('onerror') &&
243
+        typeof readyStateCallback.onerror === 'function'
244
+      ) {
245
+        readyStateCallback.onerror(ev);
246
+      }
247
+    };
248
+
249
+    ws.onmessage = function(ev) {
250
+      if (ev.data instanceof Blob) {
251
+        let reader = new FileReader();
252
+        reader.readAsArrayBuffer(ev.data);
253
+        reader.onload = function() {
254
+          try {
255
+            let packet = new Packet().unPack(this.result);
256
+            let packetLength = packet.headerLength + packet.bodyLength + 20;
257
+            if (packetLength > constant.MAX_PAYLOAD) {
258
+              throw new Error('the packet is big than ' + constant.MAX_PAYLOAD);
259
+            }
260
+
261
+            let operator = Number(packet.operator) + Number(packet.sequence);
262
+            if (_this.callback.hasOwnProperty(operator)) {
263
+              if (packet.body === '') {
264
+                packet.body = '{}';
265
+              }
266
+              _this.responseHeader = packet.header;
267
+              _this.callback[operator](JSON.parse(packet.body));
268
+            }
269
+            if (operator !== 0 && packet.body !== 'null') {
270
+              console.info('receive data', packet.body);
271
+            }
272
+          } catch (e) {
273
+            console.info(e);
274
+            throw new Error(e);
275
+          }
276
+        };
277
+      } else {
278
+        throw new Error('websocket unsupported data format');
279
+      }
280
+    };
281
+
282
+    return ws;
283
+  }
284
+
285
+  reconnect() {
286
+    if (!this.reconnectLock) {
287
+      this.reconnectLock = true;
288
+      console.info('websocket reconnect in ' + this.reconnectTimes + 's');
289
+      // 尝试重连
290
+      setTimeout(() => {
291
+        this.reconnectTimes++;
292
+        this.socket = this.connect();
293
+        this.reconnectLock = false;
294
+      }, this.reconnectTimes * 1000);
295
+    }
296
+  }
297
+}

+ 20
- 20
src/packet.ts Bestand weergeven

@@ -2,22 +2,22 @@ import { Utils } from './utils';
2 2
 import * as Int64 from 'node-int64';
3 3
 
4 4
 export class Packet {
5
-  private static key = 'b8ca9aa66def05ff3f24919274bb4a66';
6
-  private static operator: number;
7
-  private static sequence: number;
8
-  private static headerLength: number;
9
-  private static bodyLength: number;
10
-  private static header: string;
11
-  private static body: string;
5
+  private key: string = 'b8ca9aa66def05ff3f24919274bb4a66';
6
+  public operator: number;
7
+  public sequence: number;
8
+  public headerLength: number;
9
+  public bodyLength: number;
10
+  public header: string;
11
+  public body: string;
12 12
 
13
-  private static pack(
13
+  public pack(
14 14
     operator: number,
15 15
     sequence: number,
16 16
     header: string,
17 17
     body: string,
18 18
   ): ArrayBuffer {
19
-    const header = Utils.encrypt(header, Packet.key, Packet.key);
20
-    const body = Utils.encrypt(body, Packet.key, Packet.key);
19
+    header = Utils.encrypt(header, this.key, this.key);
20
+    body = Utils.encrypt(body, this.key, this.key);
21 21
 
22 22
     const headerLength = header.length;
23 23
     const bodyLength = body.length;
@@ -45,24 +45,24 @@ export class Packet {
45 45
     return buf;
46 46
   }
47 47
 
48
-  private static unPack(data: ArrayBuffer): Packet {
48
+  public unPack(data: any): Packet {
49 49
     const dataView = new DataView(data);
50 50
 
51
-    Packet.operator = dataView.getUint32(0, false);
52
-    Packet.sequence = new Int64(
51
+    this.operator = dataView.getUint32(0, false);
52
+    this.sequence = new Int64(
53 53
       new Uint8Array(dataView.buffer.slice(4, 12)),
54 54
     ).toNumber();
55
-    Packet.headerLength = dataView.getUint32(12, false);
56
-    Packet.bodyLength = dataView.getUint32(16, false);
55
+    this.headerLength = dataView.getUint32(12, false);
56
+    this.bodyLength = dataView.getUint32(16, false);
57 57
 
58 58
     const header = Utils.ab2str(
59
-      dataView.buffer.slice(20, 20 + Packet.headerLength),
59
+      dataView.buffer.slice(20, 20 + this.headerLength),
60 60
     );
61
-    const body = Utils.ab2str(dataView.buffer.slice(20 + Packet.headerLength));
61
+    const body = Utils.ab2str(dataView.buffer.slice(20 + this.headerLength));
62 62
 
63
-    Packet.header = Utils.decrypt(header, Packet.key, Packet.key);
64
-    Packet.body = Utils.decrypt(body, Packet.key, Packet.key);
63
+    this.header = Utils.decrypt(header, this.key, this.key);
64
+    this.body = Utils.decrypt(body, this.key, this.key);
65 65
 
66
-    return Packet;
66
+    return this;
67 67
   }
68 68
 }