dolphindb 2.0.506 → 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 CHANGED
@@ -124,12 +124,11 @@ export declare class DdbObj<T extends DdbValue = DdbValue> {
124
124
  datatype?: DdbType;
125
125
  /** 实际数据。不同的 DdbForm, DdbType 使用 DdbValue 中不同的类型来表示实际数据 */
126
126
  value: T;
127
- /** 原始二进制数据 */
127
+ /** 原始二进制数据,仅在 parse_object 为 false 时通过 parse_message 生成的顶层对象有这个属性 */
128
128
  buffer?: Uint8Array;
129
129
  constructor(data: Partial<DdbObj> & {
130
130
  form: DdbForm;
131
131
  type: DdbType;
132
- length: number;
133
132
  });
134
133
  static parse(buf: Uint8Array, le: boolean): DdbObj<DdbValue>;
135
134
  static parse_scalar(buf: Uint8Array, le: boolean, type: DdbType): [number, DdbValue];
@@ -275,12 +274,9 @@ export declare class DDB {
275
274
  print_object_buffer: boolean;
276
275
  print_message: boolean;
277
276
  parse_object: boolean;
278
- /** message handlers */
279
- handlers: DdbMessageHandler[];
280
- /** resolver, rejector, promise of last rpc */
281
- presolver(ddbobj: DdbObj): void;
282
- prejector(error: Error): void;
283
- presult: Promise<DdbObj<DdbValue>>;
277
+ /** DdbMessage listeners */
278
+ listeners: DdbMessageListener[];
279
+ promise: Promise<any>;
284
280
  get connected(): boolean;
285
281
  /**
286
282
  Initialize an instance of DolphinDB Client using the WebSocket URL
@@ -309,6 +305,7 @@ export declare class DDB {
309
305
  password?: string;
310
306
  python?: boolean;
311
307
  });
308
+ private on_message;
312
309
  /** Establish the actual WebSocket connection to the DolphinDB corresponding to the URL
313
310
  - options?:
314
311
  - url?: DolphinDB WebSocket URL. By default, the WebSocket URL passed in when the instance is initialized is used
@@ -353,31 +350,31 @@ export declare class DDB {
353
350
  - options:
354
351
  - urgent?: 决定 `行为标识` 那一行字符串的取值(只适用于 script 和 function)
355
352
  - vars?: type === 'variable' 时必传,variable 指令中待上传的变量名
356
- - handler?: 处理本次 rpc 期间的消息
353
+ - listener?: 处理本次 rpc 期间的消息 (DdbMessage)
357
354
  - parse_object?: 在本次 rpc 期间设置 parse_object, 结束后恢复原有
358
355
  为 false 时返回的 DdbObj 仅含有 buffer 和 le,不做解析,以便后续转发、序列化
359
356
  */
360
- rpc<T extends DdbObj = DdbObj>(type: 'script' | 'function' | 'variable' | 'connect', { script, func, args, vars, urgent, handler, parse_object, }: {
357
+ rpc<T extends DdbObj = DdbObj>(type: 'script' | 'function' | 'variable' | 'connect', { script, func, args, vars, urgent, listener, parse_object, }: {
361
358
  script?: string;
362
359
  func?: string;
363
360
  args?: (DdbObj | string | boolean)[];
364
361
  vars?: string[];
365
362
  urgent?: boolean;
366
- handler?: DdbMessageHandler;
363
+ listener?: DdbMessageListener;
367
364
  parse_object?: boolean;
368
365
  }): Promise<T>;
369
366
  /** eval script through websocket (script command)
370
367
  - script?: Script to execute
371
368
  - options?: execution options
372
369
  - urgent?: Urgent flag to ensure that submitted scripts are processed by urgent workers to prevent being blocked by other jobs
373
- - handler?: Process messages during this rpc
370
+ - listener?: Process messages during this rpc (DdbMessage)
374
371
  - parse_object?: Set parse_object during this rpc, and restore the original after the end.
375
372
  When it is false, the returned DdbObj only contains buffer and le without parsing,
376
373
  so as to facilitate subsequent forwarding and serialization
377
374
  */
378
- eval<T extends DdbObj>(script: string, { urgent, handler, parse_object, }?: {
375
+ eval<T extends DdbObj>(script: string, { urgent, listener, parse_object, }?: {
379
376
  urgent?: boolean;
380
- handler?: DdbMessageHandler;
377
+ listener?: DdbMessageListener;
381
378
  parse_object?: boolean;
382
379
  }): Promise<T>;
383
380
  /** call function through websocket (function command)
@@ -389,18 +386,18 @@ export declare class DDB {
389
386
  - nodes?: When setting multiple node aliases, send them to the corresponding multiple nodes in the cluster for execution (using the pnodeRun method in DolphinDB)
390
387
  - 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
391
388
  - add_node_alias?: Select to pass when setting the nodes parameter, otherwise not pass
392
- - handler?: Process messages during this rpc
389
+ - listener?: Process messages during this rpc (DdbMessage)
393
390
  - parse_object?: Set parse_object during this rpc, and restore the original after the end.
394
391
  When it is false, the returned DdbObj only contains buffer and le without parsing,
395
392
  so as to facilitate subsequent forwarding and serialization
396
393
  */
397
- call<T extends DdbObj>(func: string, args?: (DdbObj | string | boolean)[], { urgent, node, nodes, func_type, add_node_alias, handler, parse_object, }?: {
394
+ call<T extends DdbObj>(func: string, args?: (DdbObj | string | boolean)[], { urgent, node, nodes, func_type, add_node_alias, listener, parse_object, }?: {
398
395
  urgent?: boolean;
399
396
  node?: string;
400
397
  nodes?: string[];
401
398
  func_type?: DdbFunctionType;
402
399
  add_node_alias?: boolean;
403
- handler?: DdbMessageHandler;
400
+ listener?: DdbMessageListener;
404
401
  parse_object?: boolean;
405
402
  }): Promise<T>;
406
403
  /** upload variable through websocket (variable command) */
@@ -408,8 +405,8 @@ export declare class DDB {
408
405
  /** Uploaded variables' name */
409
406
  vars: string[],
410
407
  /** Uploaded variables' value */
411
- args: (DdbObj | string | boolean)[], { handler, parse_object, }?: {
412
- handler?: DdbMessageHandler;
408
+ args: (DdbObj | string | boolean)[], { listener, parse_object, }?: {
409
+ listener?: DdbMessageListener;
413
410
  parse_object?: boolean;
414
411
  }): Promise<DdbObj<DdbValue>>;
415
412
  /** 解析服务端响应报文,返回去掉 header 的 data buf */
@@ -419,7 +416,7 @@ export declare class DDB {
419
416
  /** 转换 js 数组为 DdbObj[] */
420
417
  to_ddbobjs(values: any[]): DdbObj<DdbValue>[];
421
418
  }
422
- export interface DdbMessageHandler {
419
+ export interface DdbMessageListener {
423
420
  (message: DdbMessage, _this: DDB): any;
424
421
  }
425
422
  export interface DdbPrintMessage {
package/browser.js CHANGED
@@ -890,21 +890,26 @@ class DdbObj {
890
890
  for (let i = 0; i < this.rows; i++) {
891
891
  let row = {};
892
892
  for (let j = 0; j < this.cols; j++) {
893
- const { type, name, value } = this.value[j]; // column
893
+ const { type, name, value: values } = this.value[j]; // column
894
894
  switch (type) {
895
- case DdbType.bool:
896
- row[name] = Boolean(value[i]);
895
+ case DdbType.bool: {
896
+ const value = values[i];
897
+ row[name] = value === exports.nulls.int8 ?
898
+ null
899
+ :
900
+ Boolean(value);
897
901
  break;
902
+ }
898
903
  case DdbType.ipaddr:
899
- row[name] = value.subarray(16 * i, 16 * (i + 1));
904
+ row[name] = values.subarray(16 * i, 16 * (i + 1));
900
905
  break;
901
906
  case DdbType.symbol_extended: {
902
- const { base, data } = value;
907
+ const { base, data } = values;
903
908
  row[name] = base[data[i]];
904
909
  break;
905
910
  }
906
911
  default:
907
- row[name] = value[i];
912
+ row[name] = values[i];
908
913
  }
909
914
  }
910
915
  rows[i] = row;
@@ -1371,9 +1376,9 @@ class DDB {
1371
1376
  this.print_object_buffer = false;
1372
1377
  this.print_message = true;
1373
1378
  this.parse_object = true;
1374
- /** message handlers */
1375
- this.handlers = [];
1376
- this.presult = Promise.resolve(null);
1379
+ /** DdbMessage listeners */
1380
+ this.listeners = [];
1381
+ this.promise = Promise.resolve(null);
1377
1382
  if (!url) {
1378
1383
  const _url = new URL(location.href);
1379
1384
  const hostname = _url.searchParams.get('hostname') || location.hostname;
@@ -1390,12 +1395,10 @@ class DDB {
1390
1395
  if (options.python !== undefined)
1391
1396
  this.python = options.python;
1392
1397
  }
1393
- /** resolver, rejector, promise of last rpc */
1394
- presolver(ddbobj) { }
1395
- prejector(error) { }
1396
1398
  get connected() {
1397
1399
  return this.websocket?.readyState === WebSocket.OPEN;
1398
1400
  }
1401
+ on_message(event) { }
1399
1402
  /** Establish the actual WebSocket connection to the DolphinDB corresponding to the URL
1400
1403
  - options?:
1401
1404
  - url?: DolphinDB WebSocket URL. By default, the WebSocket URL passed in when the instance is initialized is used
@@ -1423,30 +1426,7 @@ class DDB {
1423
1426
  await this.rpc('connect', {});
1424
1427
  },
1425
1428
  on_message: event => {
1426
- const buf = new Uint8Array(event.data);
1427
- if (this.print_message_buffer)
1428
- console.log(buf);
1429
- const message = this.parse_message(buf);
1430
- if (this.handlers.length) {
1431
- const _handlers = [...this.handlers].reverse();
1432
- for (const handler of _handlers)
1433
- handler(message, this);
1434
- }
1435
- const { type, data } = message;
1436
- switch (type) {
1437
- case 'print':
1438
- if (this.print_message)
1439
- console.log(data);
1440
- return;
1441
- case 'object':
1442
- if (this.print_object_buffer)
1443
- console.log(data.buffer);
1444
- this.presolver(data);
1445
- return;
1446
- case 'error':
1447
- this.prejector(data);
1448
- return;
1449
- }
1429
+ this.on_message(event);
1450
1430
  }
1451
1431
  });
1452
1432
  await this.eval(this.python ?
@@ -1524,45 +1504,64 @@ class DDB {
1524
1504
  disconnect() {
1525
1505
  if (this.connected)
1526
1506
  this.websocket.close(1000);
1527
- this.presolver = buf => { };
1528
- this.prejector = error => { };
1529
- this.presult = Promise.resolve(null);
1507
+ this.on_message = () => { };
1508
+ this.promise = Promise.resolve(null);
1530
1509
  }
1531
1510
  /** rpc through websocket (function/script/variable command)
1532
1511
  - type: API 类型: 'script' | 'function' | 'variable'
1533
1512
  - options:
1534
1513
  - urgent?: 决定 `行为标识` 那一行字符串的取值(只适用于 script 和 function)
1535
1514
  - vars?: type === 'variable' 时必传,variable 指令中待上传的变量名
1536
- - handler?: 处理本次 rpc 期间的消息
1515
+ - listener?: 处理本次 rpc 期间的消息 (DdbMessage)
1537
1516
  - parse_object?: 在本次 rpc 期间设置 parse_object, 结束后恢复原有
1538
1517
  为 false 时返回的 DdbObj 仅含有 buffer 和 le,不做解析,以便后续转发、序列化
1539
1518
  */
1540
- async rpc(type, { script, func, args = [], vars = [], urgent, handler, parse_object, }) {
1519
+ async rpc(type, { script, func, args = [], vars = [], urgent, listener, parse_object, }) {
1541
1520
  if (!this.websocket)
1542
1521
  await this.connect();
1543
1522
  if (!this.connected)
1544
1523
  throw new Error(`${this.url} is already disconnected`);
1524
+ // this 上的当前配置需要在 message 到达后使用,先保存起来
1525
+ const _handlers = [...this.listeners].reverse();
1545
1526
  // 临界区:保证多个 rpc 并发时形成 promise 链
1546
1527
  // ddb 世界观:需要等待上一个 rpc 结果从 server 返回之后才能发起下一个调用
1547
1528
  // 违反世界观可能造成:
1548
1529
  // 1. 并发多个请求只返回第一个结果(阻塞,需后续请求疏通)
1549
1530
  // 2. windows 下 ddb server 返回多个相同的结果
1550
- const ptail = this.presult;
1551
- let presolver;
1552
- let prejector;
1553
- const presult = this.presult = new Promise((resolve, reject) => {
1554
- presolver = resolve;
1555
- prejector = reject;
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;
1556
1537
  });
1557
1538
  try {
1558
1539
  await ptail;
1559
1540
  }
1560
1541
  catch { }
1561
- this.presolver = presolver;
1562
- this.prejector = prejector;
1563
- // 临界区结束,只有一个 rpc 请求可以写 WebSocket
1564
- if (urgent && type !== 'script' && type !== 'function')
1565
- throw new Error('urgent 只适用于 script 和 funciton');
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
+ };
1566
1565
  args = this.to_ddbobjs(args);
1567
1566
  const command = this.enc.encode((() => {
1568
1567
  switch (type) {
@@ -1583,37 +1582,24 @@ class DDB {
1583
1582
  return 'connect\n';
1584
1583
  }
1585
1584
  })());
1586
- const message = (0, utils_browser_1.concat)([
1585
+ this.websocket.send((0, utils_browser_1.concat)([
1587
1586
  this.enc.encode(`API2 ${this.sid} ${command.length} / ${this.get_rpc_options({ urgent })}\n`),
1588
1587
  command,
1589
1588
  ...args.map((arg) => arg.pack())
1590
- ]);
1591
- const _parse_object = this.parse_object;
1592
- if (handler)
1593
- this.handlers.push(handler);
1594
- if (parse_object !== undefined)
1595
- this.parse_object = parse_object;
1596
- try {
1597
- this.websocket.send(message);
1598
- return (await presult);
1599
- }
1600
- finally {
1601
- if (handler)
1602
- this.handlers = this.handlers.filter(h => h !== handler);
1603
- this.parse_object = _parse_object;
1604
- }
1589
+ ]));
1590
+ return promise;
1605
1591
  }
1606
1592
  /** eval script through websocket (script command)
1607
1593
  - script?: Script to execute
1608
1594
  - options?: execution options
1609
1595
  - urgent?: Urgent flag to ensure that submitted scripts are processed by urgent workers to prevent being blocked by other jobs
1610
- - handler?: Process messages during this rpc
1596
+ - listener?: Process messages during this rpc (DdbMessage)
1611
1597
  - parse_object?: Set parse_object during this rpc, and restore the original after the end.
1612
1598
  When it is false, the returned DdbObj only contains buffer and le without parsing,
1613
1599
  so as to facilitate subsequent forwarding and serialization
1614
1600
  */
1615
- async eval(script, { urgent, handler, parse_object, } = {}) {
1616
- return this.rpc('script', { script, urgent, handler, parse_object });
1601
+ async eval(script, { urgent, listener, parse_object, } = {}) {
1602
+ return this.rpc('script', { script, urgent, listener, parse_object });
1617
1603
  }
1618
1604
  /** call function through websocket (function command)
1619
1605
  - func: function name
@@ -1624,12 +1610,12 @@ class DDB {
1624
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)
1625
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
1626
1612
  - add_node_alias?: Select to pass when setting the nodes parameter, otherwise not pass
1627
- - handler?: Process messages during this rpc
1613
+ - listener?: Process messages during this rpc (DdbMessage)
1628
1614
  - parse_object?: Set parse_object during this rpc, and restore the original after the end.
1629
1615
  When it is false, the returned DdbObj only contains buffer and le without parsing,
1630
1616
  so as to facilitate subsequent forwarding and serialization
1631
1617
  */
1632
- async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias, handler, parse_object, } = {}) {
1618
+ async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias, listener, parse_object, } = {}) {
1633
1619
  if (node) {
1634
1620
  if (typeof func_type === 'undefined')
1635
1621
  throw new Error('指定 node 时必须设置 func_type');
@@ -1659,7 +1645,7 @@ class DDB {
1659
1645
  func,
1660
1646
  args,
1661
1647
  urgent,
1662
- handler,
1648
+ listener,
1663
1649
  parse_object
1664
1650
  });
1665
1651
  }
@@ -1668,10 +1654,10 @@ class DDB {
1668
1654
  /** Uploaded variables' name */
1669
1655
  vars,
1670
1656
  /** Uploaded variables' value */
1671
- args, { handler, parse_object, } = {}) {
1657
+ args, { listener, parse_object, } = {}) {
1672
1658
  if (!args.length || args.length !== vars.length)
1673
1659
  throw new Error('variable 指令参数为空或参数名为空,或数量不匹配');
1674
- return this.rpc('variable', { vars, args, handler, parse_object });
1660
+ return this.rpc('variable', { vars, args, listener, parse_object });
1675
1661
  }
1676
1662
  /** 解析服务端响应报文,返回去掉 header 的 data buf */
1677
1663
  parse_message(buf, parse_object = this.parse_object) {
@@ -1709,10 +1695,12 @@ class DDB {
1709
1695
  data: new Error(message)
1710
1696
  };
1711
1697
  const buf_obj = buf.subarray(i_lf_1 + 1);
1698
+ if (this.print_object_buffer)
1699
+ console.log(buf_obj);
1712
1700
  return {
1713
1701
  type: 'object',
1714
1702
  data: parse_object ?
1715
- Object.assign(DdbObj.parse(buf_obj, this.le), { buffer: buf_obj })
1703
+ DdbObj.parse(buf_obj, this.le)
1716
1704
  :
1717
1705
  new DdbObj({
1718
1706
  form: DdbForm.scalar,