dolphindb 2.0.504 → 2.0.507
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/browser.d.ts +69 -39
- package/browser.js +174 -122
- package/browser.js.map +1 -1
- package/index.d.ts +68 -39
- package/index.js +172 -129
- package/index.js.map +1 -1
- package/package.json +4 -4
package/browser.js
CHANGED
|
@@ -7,6 +7,7 @@ const customParseFormat_js_1 = tslib_1.__importDefault(require("dayjs/plugin/cus
|
|
|
7
7
|
dayjs_1.default.extend(customParseFormat_js_1.default);
|
|
8
8
|
require("xshell/prototype.browser");
|
|
9
9
|
const utils_browser_1 = require("xshell/utils.browser");
|
|
10
|
+
const net_browser_js_1 = require("xshell/net.browser.js");
|
|
10
11
|
var DdbForm;
|
|
11
12
|
(function (DdbForm) {
|
|
12
13
|
DdbForm[DdbForm["scalar"] = 0] = "scalar";
|
|
@@ -72,8 +73,7 @@ var DdbFunctionType;
|
|
|
72
73
|
DdbFunctionType[DdbFunctionType["JitPartialFunc"] = 8] = "JitPartialFunc";
|
|
73
74
|
})(DdbFunctionType = exports.DdbFunctionType || (exports.DdbFunctionType = {}));
|
|
74
75
|
exports.nulls = {
|
|
75
|
-
|
|
76
|
-
char: '\x80',
|
|
76
|
+
int8: -0x80,
|
|
77
77
|
int16: -32768,
|
|
78
78
|
int32: -2147483648,
|
|
79
79
|
int64: -0x8000000000000000n,
|
|
@@ -247,12 +247,14 @@ class DdbObj {
|
|
|
247
247
|
case DdbType.void:
|
|
248
248
|
return [1, null];
|
|
249
249
|
case DdbType.bool: {
|
|
250
|
-
const
|
|
251
|
-
|
|
250
|
+
const dv = new DataView(buf.buffer, buf.byteOffset);
|
|
251
|
+
const value = dv.getInt8(0);
|
|
252
|
+
return [1, value === exports.nulls.int8 ? null : Boolean(value)];
|
|
252
253
|
}
|
|
253
254
|
case DdbType.char: {
|
|
254
|
-
const
|
|
255
|
-
|
|
255
|
+
const dv = new DataView(buf.buffer, buf.byteOffset);
|
|
256
|
+
const value = dv.getInt8(0);
|
|
257
|
+
return [1, value === exports.nulls.int8 ? null : value];
|
|
256
258
|
}
|
|
257
259
|
case DdbType.short: {
|
|
258
260
|
const dv = new DataView(buf.buffer, buf.byteOffset);
|
|
@@ -437,11 +439,10 @@ class DdbObj {
|
|
|
437
439
|
static parse_vector_items(buf, le, type, length) {
|
|
438
440
|
switch (type) {
|
|
439
441
|
case DdbType.bool:
|
|
440
|
-
return [length, buf.slice(0, length)];
|
|
441
442
|
case DdbType.char:
|
|
442
443
|
return [
|
|
443
444
|
length,
|
|
444
|
-
|
|
445
|
+
new Int8Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + length))
|
|
445
446
|
];
|
|
446
447
|
case DdbType.short:
|
|
447
448
|
return [
|
|
@@ -591,17 +592,17 @@ class DdbObj {
|
|
|
591
592
|
return [Uint8Array.of(1)];
|
|
592
593
|
case DdbType.bool:
|
|
593
594
|
return [
|
|
594
|
-
|
|
595
|
-
exports.nulls.
|
|
595
|
+
Int8Array.of(value === null ?
|
|
596
|
+
exports.nulls.int8
|
|
596
597
|
:
|
|
597
598
|
Number(value))
|
|
598
599
|
];
|
|
599
600
|
case DdbType.char:
|
|
600
601
|
return [
|
|
601
|
-
|
|
602
|
-
exports.nulls.
|
|
602
|
+
Int8Array.of((value === null ?
|
|
603
|
+
exports.nulls.int8
|
|
603
604
|
:
|
|
604
|
-
value)
|
|
605
|
+
value))
|
|
605
606
|
];
|
|
606
607
|
case DdbType.short:
|
|
607
608
|
return [
|
|
@@ -743,7 +744,7 @@ class DdbObj {
|
|
|
743
744
|
case DdbType.bool:
|
|
744
745
|
return [value];
|
|
745
746
|
case DdbType.char:
|
|
746
|
-
return [
|
|
747
|
+
return [value];
|
|
747
748
|
case DdbType.short:
|
|
748
749
|
return [value];
|
|
749
750
|
case DdbType.int:
|
|
@@ -846,10 +847,18 @@ class DdbObj {
|
|
|
846
847
|
}
|
|
847
848
|
})();
|
|
848
849
|
const data = (() => {
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
850
|
+
switch (this.form) {
|
|
851
|
+
case DdbForm.pair:
|
|
852
|
+
return `${this.value[0]}, ${this.value[1]}`;
|
|
853
|
+
case DdbForm.scalar:
|
|
854
|
+
switch (this.type) {
|
|
855
|
+
case DdbType.functiondef:
|
|
856
|
+
return `'${this.value.name}'`;
|
|
857
|
+
case DdbType.string:
|
|
858
|
+
return `'${this.value}'`;
|
|
859
|
+
}
|
|
860
|
+
break;
|
|
861
|
+
}
|
|
853
862
|
return this.value;
|
|
854
863
|
})();
|
|
855
864
|
return `${type}(${this.name ? `'${this.name}', ` : ''}${data})\n`;
|
|
@@ -881,21 +890,26 @@ class DdbObj {
|
|
|
881
890
|
for (let i = 0; i < this.rows; i++) {
|
|
882
891
|
let row = {};
|
|
883
892
|
for (let j = 0; j < this.cols; j++) {
|
|
884
|
-
const { type, name, value } = this.value[j]; // column
|
|
893
|
+
const { type, name, value: values } = this.value[j]; // column
|
|
885
894
|
switch (type) {
|
|
886
|
-
case DdbType.bool:
|
|
887
|
-
|
|
895
|
+
case DdbType.bool: {
|
|
896
|
+
const value = values[i];
|
|
897
|
+
row[name] = value === exports.nulls.int8 ?
|
|
898
|
+
null
|
|
899
|
+
:
|
|
900
|
+
Boolean(value);
|
|
888
901
|
break;
|
|
902
|
+
}
|
|
889
903
|
case DdbType.ipaddr:
|
|
890
|
-
row[name] =
|
|
904
|
+
row[name] = values.subarray(16 * i, 16 * (i + 1));
|
|
891
905
|
break;
|
|
892
906
|
case DdbType.symbol_extended: {
|
|
893
|
-
const { base, data } =
|
|
907
|
+
const { base, data } = values;
|
|
894
908
|
row[name] = base[data[i]];
|
|
895
909
|
break;
|
|
896
910
|
}
|
|
897
911
|
default:
|
|
898
|
-
row[name] =
|
|
912
|
+
row[name] = values[i];
|
|
899
913
|
}
|
|
900
914
|
}
|
|
901
915
|
rows[i] = row;
|
|
@@ -949,7 +963,10 @@ class DdbChar extends DdbObj {
|
|
|
949
963
|
form: DdbForm.scalar,
|
|
950
964
|
type: DdbType.char,
|
|
951
965
|
length: 1,
|
|
952
|
-
value
|
|
966
|
+
value: typeof value === 'string' ?
|
|
967
|
+
value.charCodeAt(0)
|
|
968
|
+
:
|
|
969
|
+
value
|
|
953
970
|
});
|
|
954
971
|
}
|
|
955
972
|
}
|
|
@@ -1330,7 +1347,7 @@ class DDB {
|
|
|
1330
1347
|
@example
|
|
1331
1348
|
let ddb = new DDB('ws://127.0.0.1:8848')
|
|
1332
1349
|
|
|
1333
|
-
//
|
|
1350
|
+
// Encrypt with HTTPS
|
|
1334
1351
|
let ddbsecure = new DDB('wss://dolphindb.com', {
|
|
1335
1352
|
autologin: true,
|
|
1336
1353
|
username: 'admin',
|
|
@@ -1355,8 +1372,13 @@ class DDB {
|
|
|
1355
1372
|
this.password = '123456';
|
|
1356
1373
|
/** python session flag (2048) */
|
|
1357
1374
|
this.python = false;
|
|
1358
|
-
this.
|
|
1359
|
-
this.
|
|
1375
|
+
this.print_message_buffer = false;
|
|
1376
|
+
this.print_object_buffer = false;
|
|
1377
|
+
this.print_message = true;
|
|
1378
|
+
this.parse_object = true;
|
|
1379
|
+
/** DdbMessage listeners */
|
|
1380
|
+
this.listeners = [];
|
|
1381
|
+
this.promise = Promise.resolve(null);
|
|
1360
1382
|
if (!url) {
|
|
1361
1383
|
const _url = new URL(location.href);
|
|
1362
1384
|
const hostname = _url.searchParams.get('hostname') || location.hostname;
|
|
@@ -1373,16 +1395,10 @@ class DDB {
|
|
|
1373
1395
|
if (options.python !== undefined)
|
|
1374
1396
|
this.python = options.python;
|
|
1375
1397
|
}
|
|
1376
|
-
/** print message handler */
|
|
1377
|
-
printer(message) {
|
|
1378
|
-
console.log(message);
|
|
1379
|
-
}
|
|
1380
|
-
/** resolver, rejector, promise of last rpc */
|
|
1381
|
-
presolver(buf) { }
|
|
1382
|
-
prejector(error) { }
|
|
1383
1398
|
get connected() {
|
|
1384
1399
|
return this.websocket?.readyState === WebSocket.OPEN;
|
|
1385
1400
|
}
|
|
1401
|
+
on_message(event) { }
|
|
1386
1402
|
/** Establish the actual WebSocket connection to the DolphinDB corresponding to the URL
|
|
1387
1403
|
- options?:
|
|
1388
1404
|
- url?: DolphinDB WebSocket URL. By default, the WebSocket URL passed in when the instance is initialized is used
|
|
@@ -1403,58 +1419,51 @@ class DDB {
|
|
|
1403
1419
|
if (options.python !== undefined)
|
|
1404
1420
|
this.python = options.python;
|
|
1405
1421
|
this.disconnect();
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
await new Promise((resolve, reject) => {
|
|
1411
|
-
websocket.addEventListener('open', async (event) => {
|
|
1412
|
-
console.log(`${websocket.url} opened`);
|
|
1422
|
+
await (0, net_browser_js_1.connect_websocket)(this.url, {
|
|
1423
|
+
protocols: this.python ? ['python'] : [],
|
|
1424
|
+
on_open: async (event, websocket) => {
|
|
1425
|
+
this.websocket = websocket;
|
|
1413
1426
|
await this.rpc('connect', {});
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
});
|
|
1419
|
-
websocket.addEventListener('error', event => {
|
|
1420
|
-
const message = `${websocket.url} errored`;
|
|
1421
|
-
console.error(message, event);
|
|
1422
|
-
reject(Object.assign(new Error(message), { event }));
|
|
1423
|
-
});
|
|
1424
|
-
websocket.addEventListener('message', event => {
|
|
1425
|
-
const buf = new Uint8Array(event.data);
|
|
1426
|
-
if (this.message_hook)
|
|
1427
|
-
this.message_hook(buf);
|
|
1428
|
-
try {
|
|
1429
|
-
const { type, data } = this.parse_message(buf);
|
|
1430
|
-
if (type === 'message') {
|
|
1431
|
-
this.printer(data);
|
|
1432
|
-
return;
|
|
1433
|
-
}
|
|
1434
|
-
this.presolver(data);
|
|
1435
|
-
}
|
|
1436
|
-
catch (error) {
|
|
1437
|
-
this.prejector(error);
|
|
1438
|
-
}
|
|
1439
|
-
});
|
|
1427
|
+
},
|
|
1428
|
+
on_message: event => {
|
|
1429
|
+
this.on_message(event);
|
|
1430
|
+
}
|
|
1440
1431
|
});
|
|
1441
|
-
|
|
1442
|
-
|
|
1432
|
+
await this.eval(this.python ?
|
|
1433
|
+
'def pnode_run (nodes, func_name, args, add_node_alias):\n' +
|
|
1443
1434
|
' nargs = size(args)\n' +
|
|
1444
1435
|
' func = funcByName(func_name)\n' +
|
|
1445
1436
|
' \n' +
|
|
1446
|
-
' if
|
|
1437
|
+
' if not nargs:\n' +
|
|
1447
1438
|
' return pnodeRun(func, nodes, add_node_alias)\n' +
|
|
1448
1439
|
' \n' +
|
|
1449
|
-
' args_partial =
|
|
1450
|
-
' args_partial
|
|
1451
|
-
'
|
|
1440
|
+
' args_partial = [ ]\n' +
|
|
1441
|
+
' args_partial.append(func)\n' +
|
|
1442
|
+
' for a in args:\n' +
|
|
1443
|
+
' args_partial.append(a)\n' +
|
|
1444
|
+
' \n' +
|
|
1452
1445
|
' return pnodeRun(\n' +
|
|
1453
1446
|
' unifiedCall(partial, args_partial),\n' +
|
|
1454
1447
|
' nodes,\n' +
|
|
1455
1448
|
' add_node_alias\n' +
|
|
1456
|
-
' )\n'
|
|
1457
|
-
|
|
1449
|
+
' )\n'
|
|
1450
|
+
:
|
|
1451
|
+
'def pnode_run (nodes, func_name, args, add_node_alias = true) {\n' +
|
|
1452
|
+
' nargs = size(args)\n' +
|
|
1453
|
+
' func = funcByName(func_name)\n' +
|
|
1454
|
+
' \n' +
|
|
1455
|
+
' if (!nargs)\n' +
|
|
1456
|
+
' return pnodeRun(func, nodes, add_node_alias)\n' +
|
|
1457
|
+
' \n' +
|
|
1458
|
+
' args_partial = array(any, 1 + nargs, 1 + nargs)\n' +
|
|
1459
|
+
' args_partial[0] = func\n' +
|
|
1460
|
+
' args_partial[1:] = args\n' +
|
|
1461
|
+
' return pnodeRun(\n' +
|
|
1462
|
+
' unifiedCall(partial, args_partial),\n' +
|
|
1463
|
+
' nodes,\n' +
|
|
1464
|
+
' add_node_alias\n' +
|
|
1465
|
+
' )\n' +
|
|
1466
|
+
'}\n', { urgent: true });
|
|
1458
1467
|
if (this.autologin)
|
|
1459
1468
|
if (this.python)
|
|
1460
1469
|
await this.eval(`login(${this.username.quote('double')}, ${this.password.quote('double')})`, { urgent: true });
|
|
@@ -1490,47 +1499,69 @@ class DDB {
|
|
|
1490
1499
|
limit,
|
|
1491
1500
|
] : [],
|
|
1492
1501
|
];
|
|
1493
|
-
return
|
|
1502
|
+
return options.join('_');
|
|
1494
1503
|
}
|
|
1495
1504
|
disconnect() {
|
|
1496
1505
|
if (this.connected)
|
|
1497
1506
|
this.websocket.close(1000);
|
|
1498
|
-
this.
|
|
1499
|
-
this.
|
|
1500
|
-
this.presult = Promise.resolve(null);
|
|
1507
|
+
this.on_message = () => { };
|
|
1508
|
+
this.promise = Promise.resolve(null);
|
|
1501
1509
|
}
|
|
1502
1510
|
/** rpc through websocket (function/script/variable command)
|
|
1503
1511
|
- type: API 类型: 'script' | 'function' | 'variable'
|
|
1504
1512
|
- options:
|
|
1505
1513
|
- urgent?: 决定 `行为标识` 那一行字符串的取值(只适用于 script 和 function)
|
|
1506
1514
|
- vars?: type === 'variable' 时必传,variable 指令中待上传的变量名
|
|
1515
|
+
- listener?: 处理本次 rpc 期间的消息 (DdbMessage)
|
|
1516
|
+
- parse_object?: 在本次 rpc 期间设置 parse_object, 结束后恢复原有
|
|
1517
|
+
为 false 时返回的 DdbObj 仅含有 buffer 和 le,不做解析,以便后续转发、序列化
|
|
1507
1518
|
*/
|
|
1508
|
-
async rpc(type, { script, func, args = [], vars = [], urgent, }) {
|
|
1519
|
+
async rpc(type, { script, func, args = [], vars = [], urgent, listener, parse_object, }) {
|
|
1509
1520
|
if (!this.websocket)
|
|
1510
1521
|
await this.connect();
|
|
1511
1522
|
if (!this.connected)
|
|
1512
1523
|
throw new Error(`${this.url} is already disconnected`);
|
|
1524
|
+
// this 上的当前配置需要在 message 到达后使用,先保存起来
|
|
1525
|
+
const _handlers = [...this.listeners].reverse();
|
|
1513
1526
|
// 临界区:保证多个 rpc 并发时形成 promise 链
|
|
1514
1527
|
// ddb 世界观:需要等待上一个 rpc 结果从 server 返回之后才能发起下一个调用
|
|
1515
1528
|
// 违反世界观可能造成:
|
|
1516
1529
|
// 1. 并发多个请求只返回第一个结果(阻塞,需后续请求疏通)
|
|
1517
1530
|
// 2. windows 下 ddb server 返回多个相同的结果
|
|
1518
|
-
const ptail = this.
|
|
1519
|
-
let
|
|
1520
|
-
let
|
|
1521
|
-
const
|
|
1522
|
-
|
|
1523
|
-
|
|
1531
|
+
const ptail = this.promise;
|
|
1532
|
+
let resolve;
|
|
1533
|
+
let reject;
|
|
1534
|
+
const promise = this.promise = new Promise((_resolve, _reject) => {
|
|
1535
|
+
resolve = _resolve;
|
|
1536
|
+
reject = _reject;
|
|
1524
1537
|
});
|
|
1525
1538
|
try {
|
|
1526
1539
|
await ptail;
|
|
1527
1540
|
}
|
|
1528
1541
|
catch { }
|
|
1529
|
-
this.
|
|
1530
|
-
this.
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1542
|
+
// 临界区结束,只有一个 rpc 函数调用运行到这里,可以独占 this.on_message 然后写 WebSocket
|
|
1543
|
+
this.on_message = ({ data: buffer }) => {
|
|
1544
|
+
const buf = new Uint8Array(buffer);
|
|
1545
|
+
if (this.print_message_buffer)
|
|
1546
|
+
console.log(buf);
|
|
1547
|
+
const message = this.parse_message(buf, parse_object);
|
|
1548
|
+
listener?.(message, this);
|
|
1549
|
+
for (const listener of _handlers)
|
|
1550
|
+
listener(message, this);
|
|
1551
|
+
const { type, data } = message;
|
|
1552
|
+
switch (type) {
|
|
1553
|
+
case 'print':
|
|
1554
|
+
if (this.print_message)
|
|
1555
|
+
console.log(data);
|
|
1556
|
+
return;
|
|
1557
|
+
case 'object':
|
|
1558
|
+
resolve(data);
|
|
1559
|
+
return;
|
|
1560
|
+
case 'error':
|
|
1561
|
+
reject(data);
|
|
1562
|
+
return;
|
|
1563
|
+
}
|
|
1564
|
+
};
|
|
1534
1565
|
args = this.to_ddbobjs(args);
|
|
1535
1566
|
const command = this.enc.encode((() => {
|
|
1536
1567
|
switch (type) {
|
|
@@ -1551,36 +1582,40 @@ class DDB {
|
|
|
1551
1582
|
return 'connect\n';
|
|
1552
1583
|
}
|
|
1553
1584
|
})());
|
|
1554
|
-
|
|
1555
|
-
this.enc.encode(`API2 ${this.sid} ${command.length}${this.get_rpc_options({ urgent })}\n`),
|
|
1585
|
+
this.websocket.send((0, utils_browser_1.concat)([
|
|
1586
|
+
this.enc.encode(`API2 ${this.sid} ${command.length} / ${this.get_rpc_options({ urgent })}\n`),
|
|
1556
1587
|
command,
|
|
1557
1588
|
...args.map((arg) => arg.pack())
|
|
1558
|
-
]);
|
|
1559
|
-
|
|
1560
|
-
return DdbObj.parse(await presult, // data_buf
|
|
1561
|
-
this.le);
|
|
1589
|
+
]));
|
|
1590
|
+
return promise;
|
|
1562
1591
|
}
|
|
1563
|
-
/** eval script through websocket (script command)
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1592
|
+
/** eval script through websocket (script command)
|
|
1593
|
+
- script?: Script to execute
|
|
1594
|
+
- options?: execution options
|
|
1595
|
+
- urgent?: Urgent flag to ensure that submitted scripts are processed by urgent workers to prevent being blocked by other jobs
|
|
1596
|
+
- listener?: Process messages during this rpc (DdbMessage)
|
|
1597
|
+
- parse_object?: Set parse_object during this rpc, and restore the original after the end.
|
|
1598
|
+
When it is false, the returned DdbObj only contains buffer and le without parsing,
|
|
1599
|
+
so as to facilitate subsequent forwarding and serialization
|
|
1600
|
+
*/
|
|
1601
|
+
async eval(script, { urgent, listener, parse_object, } = {}) {
|
|
1602
|
+
return this.rpc('script', { script, urgent, listener, parse_object });
|
|
1570
1603
|
}
|
|
1571
1604
|
/** call function through websocket (function command)
|
|
1572
|
-
- func:
|
|
1573
|
-
- args?: `[ ]`
|
|
1574
|
-
- options?:
|
|
1575
|
-
- urgent?:
|
|
1576
|
-
- node?:
|
|
1577
|
-
- nodes?:
|
|
1578
|
-
- func_type?:
|
|
1579
|
-
- add_node_alias?:
|
|
1605
|
+
- func: function name
|
|
1606
|
+
- args?: `[ ]` Call parameters (the incoming native string and boolean will be automatically converted to DdbObj<string> and DdbObj<boolean>)
|
|
1607
|
+
- options?: call options
|
|
1608
|
+
- urgent?: Emergency flag. Use urgent worker execution to prevent being blocked by other jobs
|
|
1609
|
+
- node?: When the node alias is set, it is sent to the corresponding node in the cluster for execution (using the rpc method in DolphinDB)
|
|
1610
|
+
- nodes?: When setting multiple node aliases, send them to the corresponding multiple nodes in the cluster for execution (using the pnodeRun method in DolphinDB)
|
|
1611
|
+
- func_type?: It must be passed when setting the node parameter, the function type needs to be specified, and it is not passed in other cases
|
|
1612
|
+
- add_node_alias?: Select to pass when setting the nodes parameter, otherwise not pass
|
|
1613
|
+
- listener?: Process messages during this rpc (DdbMessage)
|
|
1614
|
+
- parse_object?: Set parse_object during this rpc, and restore the original after the end.
|
|
1615
|
+
When it is false, the returned DdbObj only contains buffer and le without parsing,
|
|
1616
|
+
so as to facilitate subsequent forwarding and serialization
|
|
1580
1617
|
*/
|
|
1581
|
-
async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias } = {}) {
|
|
1582
|
-
if (this.python)
|
|
1583
|
-
throw new Error('call doesn\'t support python session yet');
|
|
1618
|
+
async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias, listener, parse_object, } = {}) {
|
|
1584
1619
|
if (node) {
|
|
1585
1620
|
if (typeof func_type === 'undefined')
|
|
1586
1621
|
throw new Error('指定 node 时必须设置 func_type');
|
|
@@ -1610,6 +1645,8 @@ class DDB {
|
|
|
1610
1645
|
func,
|
|
1611
1646
|
args,
|
|
1612
1647
|
urgent,
|
|
1648
|
+
listener,
|
|
1649
|
+
parse_object
|
|
1613
1650
|
});
|
|
1614
1651
|
}
|
|
1615
1652
|
/** upload variable through websocket (variable command) */
|
|
@@ -1617,19 +1654,19 @@ class DDB {
|
|
|
1617
1654
|
/** Uploaded variables' name */
|
|
1618
1655
|
vars,
|
|
1619
1656
|
/** Uploaded variables' value */
|
|
1620
|
-
args) {
|
|
1657
|
+
args, { listener, parse_object, } = {}) {
|
|
1621
1658
|
if (!args.length || args.length !== vars.length)
|
|
1622
1659
|
throw new Error('variable 指令参数为空或参数名为空,或数量不匹配');
|
|
1623
|
-
return this.rpc('variable', { vars, args });
|
|
1660
|
+
return this.rpc('variable', { vars, args, listener, parse_object });
|
|
1624
1661
|
}
|
|
1625
1662
|
/** 解析服务端响应报文,返回去掉 header 的 data buf */
|
|
1626
|
-
parse_message(buf) {
|
|
1663
|
+
parse_message(buf, parse_object = this.parse_object) {
|
|
1627
1664
|
// MSG\n
|
|
1628
1665
|
// <message>\0
|
|
1629
1666
|
// 'M'.codePointAt(0).to_hex_str()
|
|
1630
1667
|
if (buf[0] === 0x4d && buf[1] === 0x53 && buf[2] === 0x47 && buf[3] === 0x0a)
|
|
1631
1668
|
return {
|
|
1632
|
-
type: '
|
|
1669
|
+
type: 'print',
|
|
1633
1670
|
data: this.dec.decode(buf.subarray(4))
|
|
1634
1671
|
};
|
|
1635
1672
|
// '1166953221 1 1\n'
|
|
@@ -1653,10 +1690,25 @@ class DDB {
|
|
|
1653
1690
|
/** 'OK' 表示成功,其它文本表示失败 */
|
|
1654
1691
|
const message = this.dec.decode(buf.subarray(i_ls_1, i_lf_1));
|
|
1655
1692
|
if (message !== 'OK')
|
|
1656
|
-
|
|
1693
|
+
return {
|
|
1694
|
+
type: 'error',
|
|
1695
|
+
data: new Error(message)
|
|
1696
|
+
};
|
|
1697
|
+
const buf_obj = buf.subarray(i_lf_1 + 1);
|
|
1698
|
+
if (this.print_object_buffer)
|
|
1699
|
+
console.log(buf_obj);
|
|
1657
1700
|
return {
|
|
1658
1701
|
type: 'object',
|
|
1659
|
-
data:
|
|
1702
|
+
data: parse_object ?
|
|
1703
|
+
DdbObj.parse(buf_obj, this.le)
|
|
1704
|
+
:
|
|
1705
|
+
new DdbObj({
|
|
1706
|
+
form: DdbForm.scalar,
|
|
1707
|
+
type: DdbType.void,
|
|
1708
|
+
length: 0,
|
|
1709
|
+
le: this.le,
|
|
1710
|
+
buffer: buf_obj,
|
|
1711
|
+
})
|
|
1660
1712
|
};
|
|
1661
1713
|
}
|
|
1662
1714
|
/** 自动转换 js string, boolean 为 DdbObj */
|