js-rpc2 1.0.0 → 1.0.2

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/README.md CHANGED
@@ -1,4 +1,110 @@
1
- # rpc
1
+ # js-rpc2 Library Introduction
2
+
3
+ `js-rpc2` is a lightweight Remote Procedure Call (RPC) library designed to simplify communication between clients and servers. The library supports various data types, including strings, binary data, objects, arrays, and more, and provides a powerful callback mechanism to provide real-time progress updates during asynchronous operations.
4
+
5
+ ## Main Features
6
+
7
+ - **Easy to Use**: Simple API design makes it easy to integrate both the client and server sides.
8
+ - **Support for Multiple Data Types**: Supports strings, binary data, objects, arrays, and more.
9
+ - **Callback Mechanism**: Real-time progress updates can be provided through callback functions during asynchronous operations.
10
+ - **Flexible Routing Configuration**: Supports the Koa framework, allowing you to easily integrate RPC routes into existing Koa applications.
11
+ - **Cross-Origin Support**: Clients can communicate with servers on different domains via HTTP requests.
12
+
13
+ ## Installation
14
+
15
+ ```sh
16
+ npm i js-rpc2
17
+ ```
18
+
19
+ ## Usage Example
20
+
21
+ ### Server Side
22
+
23
+ ```js
24
+ import { createServer } from 'http'
25
+ import Koa from 'koa'
26
+ import Router from 'koa-router'
27
+ import { createRpcServerKoaRouter } from 'js-rpc2/src/server.js'
28
+
29
+ const app = new Koa()
30
+ const router = new Router()
31
+ app.use(router.routes())
32
+ app.use(router.allowedMethods())
33
+ createServer(app.callback()).listen(9000)
34
+
35
+ class RpcApi {
36
+ /**
37
+ * @param {string} string
38
+ * @param {Uint8Array} buffer
39
+ * @param {Object} object
40
+ * @param {null} _null
41
+ * @param {undefined} _undefined
42
+ * @param {object[]} array
43
+ * @param {(arg1:string,arg2:number)=>void} callback
44
+ */
45
+ async hello(string, buffer, object, _null, _undefined, array, callback) {
46
+ for (let i = 0; i < 3; i++) {
47
+ callback('progress : ', i)
48
+ await new Promise((resolve) => setTimeout(resolve, 1000))
49
+ }
50
+ return [
51
+ `${typeof string}-${typeof buffer}-${typeof object}-${typeof _null}-${typeof _undefined}-${typeof array}`,
52
+ new Uint8Array(3),
53
+ { a: 1, b: 2, c: 3 },
54
+ 1,
55
+ true,
56
+ undefined,
57
+ [1, 2, 3, 4],
58
+ ]
59
+ }
60
+ }
61
+
62
+ const extension = new RpcApi()
63
+
64
+ createRpcServerKoaRouter({
65
+ path: '/rpc/abc',
66
+ router: router,
67
+ extension: extension,
68
+ })
69
+ ```
70
+
71
+ ### Client Side
72
+
73
+ ```js
74
+ import { createRpcClientHttp } from 'js-rpc2/src/client.js'
75
+
76
+ /** @type{RpcApi} */
77
+ const rpc = createRpcClientHttp({
78
+ url: `/rpc/abc`, // in same site html page
79
+ url: `http://127.0.0.1:9000/rpc/abc`, // others
80
+ })
81
+
82
+ let ret = await rpc.hello('123', new Uint8Array(3), { q: 2, w: 3, e: 4 }, null, undefined, [1, 2, 3, 4], (message, num) => {
83
+ console.info('callback', message, num)
84
+ })
85
+ console.info(ret)
86
+ ```
87
+
88
+ ## Output Example
89
+
90
+ ```sh
91
+ node --test-name-pattern="^basic$" src/lib.test.js
92
+ ✔ basic (4.5986ms)
93
+ callback progress : 0
94
+ callback progress : 1
95
+ callback progress : 2
96
+ [
97
+ 'string-object-object-object-undefined-object',
98
+ Uint8Array(3) [ 0, 0, 0 ],
99
+ { a: 1, b: 2, c: 3 },
100
+ 1,
101
+ true,
102
+ undefined,
103
+ [ 1, 2, 3, 4 ]
104
+ ]
105
+ ```
106
+
107
+ We hope that `js-rpc2` will help you build and manage communication between clients and servers more efficiently.
2
108
 
3
109
  ## example
4
110
  ```js
package/README.zh.md ADDED
@@ -0,0 +1,316 @@
1
+ # js-rpc2 库介绍
2
+
3
+ `js-rpc2` 是一个轻量级的远程过程调用(RPC)库,旨在简化客户端和服务器之间的通信。该库支持多种数据类型,包括字符串、二进制数据、对象、数组等,并且提供了强大的回调机制,以便在异步操作中实时反馈进度。
4
+
5
+ ## 主要特性
6
+
7
+ - **简单易用**:通过简单的 API 设计,使得客户端和服务器端的集成变得非常容易。
8
+ - **多种数据类型支持**:支持字符串、二进制数据、对象、数组等多种数据类型。
9
+ - **回调机制**:在异步操作中可以通过回调函数实时反馈进度。
10
+ - **灵活的路由配置**:支持 Koa 框架,可以轻松地将 RPC 路由集成到现有的 Koa 应用中。
11
+ - **跨域支持**:客户端可以通过 HTTP 请求与不同域的服务器进行通信。
12
+
13
+ ## 安装
14
+
15
+ ```sh
16
+ npm i js-rpc2
17
+ ```
18
+
19
+ ## 使用示例
20
+
21
+ ### 服务器端
22
+
23
+ ```js
24
+ import { createServer } from 'http'
25
+ import Koa from 'koa'
26
+ import Router from 'koa-router'
27
+ import { createRpcServerKoaRouter } from 'js-rpc2/src/server.js'
28
+
29
+ const app = new Koa()
30
+ const router = new Router()
31
+ app.use(router.routes())
32
+ app.use(router.allowedMethods())
33
+ createServer(app.callback()).listen(9000)
34
+
35
+ class RpcApi {
36
+ /**
37
+ * @param {string} string
38
+ * @param {Uint8Array} buffer
39
+ * @param {Object} object
40
+ * @param {null} _null
41
+ * @param {undefined} _undefined
42
+ * @param {object[]} array
43
+ * @param {(arg1:string,arg2:number)=>void} callback
44
+ */
45
+ async hello(string, buffer, object, _null, _undefined, array, callback) {
46
+ for (let i = 0; i < 3; i++) {
47
+ callback('progress : ', i)
48
+ await new Promise((resolve) => setTimeout(resolve, 1000))
49
+ }
50
+ return [
51
+ `${typeof string}-${typeof buffer}-${typeof object}-${typeof _null}-${typeof _undefined}-${typeof array}`,
52
+ new Uint8Array(3),
53
+ { a: 1, b: 2, c: 3 },
54
+ 1,
55
+ true,
56
+ undefined,
57
+ [1, 2, 3, 4],
58
+ ]
59
+ }
60
+ }
61
+
62
+ const extension = new RpcApi()
63
+
64
+ createRpcServerKoaRouter({
65
+ path: '/rpc/abc',
66
+ router: router,
67
+ extension: extension,
68
+ })
69
+ ```
70
+
71
+ ### 客户端
72
+
73
+ ```js
74
+ import { createRpcClientHttp } from 'js-rpc2/src/client.js'
75
+
76
+ /** @type{RpcApi} */
77
+ const rpc = createRpcClientHttp({
78
+ url: `/rpc/abc`, // in same site html page
79
+ url: `http://127.0.0.1:9000/rpc/abc`, // others
80
+ })
81
+
82
+ let ret = await rpc.hello('123', new Uint8Array(3), { q: 2, w: 3, e: 4 }, null, undefined, [1, 2, 3, 4], (message, num) => {
83
+ console.info('callback', message, num)
84
+ })
85
+ console.info(ret)
86
+ ```
87
+
88
+ ## 输出示例
89
+
90
+ ```sh
91
+ node --test-name-pattern="^basic$" src/lib.test.js
92
+ ✔ basic (4.5986ms)
93
+ callback progress : 0
94
+ callback progress : 1
95
+ callback progress : 2
96
+ [
97
+ 'string-object-object-object-undefined-object',
98
+ Uint8Array(3) [ 0, 0, 0 ],
99
+ { a: 1, b: 2, c: 3 },
100
+ 1,
101
+ true,
102
+ undefined,
103
+ [ 1, 2, 3, 4 ]
104
+ ]
105
+ ```
106
+
107
+ 希望 `js-rpc2` 能够帮助你更高效地构建和管理客户端与服务器之间的通信。
108
+
109
+
110
+ ## example
111
+ ```js
112
+ import { test } from 'node:test'
113
+ import { deepStrictEqual, strictEqual } from 'node:assert'
114
+ import { createRpcClientHttp, createRpcClientWebSocket, sleep, Uint8Array_from } from './lib.js'
115
+ import { createServer } from 'node:http'
116
+ import { WebSocketServer } from 'ws'
117
+ import Koa from 'koa'
118
+ import Router from 'koa-router'
119
+ import { createRpcServerKoaRouter, createRpcServerWebSocket } from './server.js'
120
+
121
+ test('测试RPC调用-WebSocket', async () => {
122
+ // node --test-name-pattern="^测试RPC调用-WebSocket$" src/lib.test.js
123
+
124
+ const extension = {
125
+ hello: async function (/** @type {string} */ name) {
126
+ return `hello ${name}`
127
+ },
128
+ callback: async function (/** @type {string} */ name, /** @type {(data: string) => void} */ update) {
129
+ for (let i = 0; i < 3; i++) {
130
+ update(`progress ${i}`)
131
+ await sleep(30)
132
+ }
133
+ return `hello callback ${name}`
134
+ },
135
+ callback2: async function (/** @type {string} */ name, /** @type {(data: string, data2:Uint8Array) => void} */ update) {
136
+ for (let i = 0; i < 3; i++) {
137
+ update(`progress ${i}`, Uint8Array_from('2345'))
138
+ await sleep(30)
139
+ }
140
+ return `hello callback ${name}`
141
+ },
142
+ buffer: async function (/** @type {Uint8Array} */ buffer) {
143
+ return buffer.slice(3, 8)
144
+ },
145
+ buffer2: async function (/**@type{string}*/string,/** @type {Uint8Array} */ buffer) {
146
+ return ['message:' + string, buffer.slice(3, 8)]
147
+ },
148
+ bigbuffer: async function (/** @type {Uint8Array} */ buffer) {
149
+ return buffer.slice(3)
150
+ },
151
+ array: async function (/** @type {string} */ name,/** @type {Uint8Array} */ buffer) {
152
+ return [123, 'abc', 'hi ' + name, buffer.slice(3, 8)]
153
+ },
154
+ void: async function (/** @type {string} */ name,/** @type {Uint8Array} */ buffer) {
155
+ console.info('call void')
156
+ }
157
+ }
158
+
159
+ await runWithAbortController(async (ac) => {
160
+ let server = createServer()
161
+ ac.signal.addEventListener('abort', () => { server.close() })
162
+ let wss = new WebSocketServer({ server })
163
+ createRpcServerWebSocket({
164
+ path: '/3f1d664e469aa24b54d6bad0d6d869c0',
165
+ wss: wss,
166
+ rpcKey: '11474f3dfbb861700cb6c3864b328311',
167
+ extension: extension,
168
+ })
169
+ server.listen(9000)
170
+ await sleep(100)
171
+
172
+ /** @type{typeof extension} */
173
+ let client = createRpcClientWebSocket({
174
+ url: `ws://127.0.0.1:9000/3f1d664e469aa24b54d6bad0d6d869c0`,
175
+ rpcKey: '11474f3dfbb861700cb6c3864b328311',
176
+ signal: ac.signal,
177
+ })
178
+ await sleep(100)
179
+
180
+ let string = await client.hello('asdfghjkl')
181
+ console.info(string)
182
+ strictEqual(string, 'hello asdfghjkl')
183
+
184
+ let stringcallback = await client.callback('asdfghjkl', (progress) => {
185
+ console.info(`client : ${progress}`)
186
+ })
187
+ strictEqual(stringcallback, 'hello callback asdfghjkl')
188
+
189
+ let callbackCount = 0
190
+ let stringcallback2 = await client.callback2('asdfghjkl', (progress, buffer) => {
191
+ console.info(`client : ${progress}`, buffer)
192
+ callbackCount++
193
+ })
194
+ strictEqual(3, callbackCount)
195
+ strictEqual(stringcallback2, 'hello callback asdfghjkl')
196
+
197
+ let buffer = Uint8Array_from('qwertyuiop')
198
+ let slice = await client.buffer(buffer)
199
+ deepStrictEqual(slice, buffer.slice(3, 8))
200
+
201
+ let slice2 = await client.buffer(new Uint8Array(300000))
202
+ deepStrictEqual(slice2, new Uint8Array(10).slice(3, 8))
203
+
204
+ let array = await client.array('asdfghjkl', buffer)
205
+ deepStrictEqual(array, [123, 'abc', 'hi asdfghjkl', buffer.slice(3, 8)])
206
+
207
+ let retvoid = await client.void('asdfghjkl', buffer)
208
+ strictEqual(retvoid, undefined)
209
+
210
+ let retbuffer2 = await client.buffer2('asdfghjkl', new Uint8Array(300000))
211
+ deepStrictEqual(retbuffer2, ['message:asdfghjkl', new Uint8Array(300).slice(3, 8)])
212
+ })
213
+
214
+ })
215
+
216
+ test('测试RPC调用-KoaRouter', async () => {
217
+ // node --test-name-pattern="^测试RPC调用-KoaRouter$" src/lib.test.js
218
+ const extension = {
219
+ hello: async function (/** @type {string} */ name) {
220
+ return `hello ${name}`
221
+ },
222
+ callback: async function (/** @type {string} */ name, /** @type {(data: string) => void} */ update) {
223
+ for (let i = 0; i < 3; i++) {
224
+ update(`progress ${i}`)
225
+ await sleep(30)
226
+ }
227
+ return `hello callback ${name}`
228
+ },
229
+ callback2: async function (/** @type {string} */ name, /** @type {(data: string, data2:Uint8Array) => void} */ update) {
230
+ for (let i = 0; i < 3; i++) {
231
+ update(`progress ${i}`, Uint8Array_from('2345'))
232
+ await sleep(30)
233
+ }
234
+ return `hello callback ${name}`
235
+ },
236
+ buffer: async function (/** @type {Uint8Array} */ buffer) {
237
+ return buffer.slice(3, 8)
238
+ },
239
+ array: async function (/** @type {string} */ name,/** @type {Uint8Array} */ buffer) {
240
+ return [123, 'abc', 'hi ' + name, buffer.slice(3, 8)]
241
+ },
242
+ void: async function (/** @type {string} */ name,/** @type {Uint8Array} */ buffer) {
243
+ console.info('call void')
244
+ }
245
+ }
246
+
247
+ await runWithAbortController(async (ac) => {
248
+ let server = createServer()
249
+ let app = new Koa()
250
+ let router = new Router()
251
+
252
+ ac.signal.addEventListener('abort', () => { server.close() })
253
+ createRpcServerKoaRouter({
254
+ path: '/3f1d664e469aa24b54d6bad0d6d869c0',
255
+ router: router,
256
+ rpcKey: '11474f3dfbb861700cb6c3864b328311',
257
+ extension: extension,
258
+ })
259
+
260
+ server.addListener('request', app.callback())
261
+ app.use(router.routes())
262
+ app.use(router.allowedMethods())
263
+
264
+ server.listen(9000)
265
+ await sleep(100)
266
+
267
+ /** @type{typeof extension} */
268
+ let client = createRpcClientHttp({
269
+ url: `http://127.0.0.1:9000/3f1d664e469aa24b54d6bad0d6d869c0`,
270
+ rpcKey: '11474f3dfbb861700cb6c3864b328311',
271
+ signal: ac.signal,
272
+ })
273
+ await sleep(100)
274
+
275
+ let string = await client.hello('asdfghjkl')
276
+ console.info(string)
277
+ strictEqual(string, 'hello asdfghjkl')
278
+
279
+ let callbackCount = 0
280
+ let stringcallback = await client.callback('asdfghjkl', (progress) => {
281
+ console.info(`client : ${progress}`)
282
+ callbackCount++
283
+ })
284
+
285
+ strictEqual(3, callbackCount)
286
+ strictEqual(stringcallback, 'hello callback asdfghjkl')
287
+
288
+ let stringcallback2 = await client.callback2('asdfghjkl', (progress, buffer) => {
289
+ console.info(`client : ${progress}`, buffer)
290
+ })
291
+ strictEqual(stringcallback2, 'hello callback asdfghjkl')
292
+
293
+ let buffer = Uint8Array_from('qwertyuiop')
294
+ let slice = await client.buffer(buffer)
295
+ deepStrictEqual(slice, buffer.slice(3, 8))
296
+
297
+ let array = await client.array('asdfghjkl', buffer)
298
+ deepStrictEqual(array, [123, 'abc', 'hi asdfghjkl', buffer.slice(3, 8)])
299
+
300
+ let retvoid = await client.void('asdfghjkl', buffer)
301
+ strictEqual(retvoid, undefined)
302
+ })
303
+ console.info('over!')
304
+ })
305
+
306
+ /**
307
+ * @param {(ac: AbortController) => Promise<void>} func
308
+ */
309
+ export async function runWithAbortController(func) {
310
+ let ac = new AbortController()
311
+ try {
312
+ await func(ac)
313
+ await sleep(1000)
314
+ } finally { ac.abort() }
315
+ }
316
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-rpc2",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "js web websocket http rpc",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/src/lib.js CHANGED
@@ -86,10 +86,10 @@ export async function buildBufferData(queue, key, iv) {
86
86
  }
87
87
 
88
88
  /**
89
- * @param {Uint8Array} buffer
89
+ * @param {Uint8Array<ArrayBuffer>} buffer
90
90
  * @param {CryptoKey} key
91
91
  * @param {Uint8Array} iv
92
- * @returns {Promise<[Uint8Array[],Uint8Array]>}
92
+ * @returns {Promise<[Uint8Array[],Uint8Array<ArrayBuffer>]>}
93
93
  */
94
94
  export async function parseBufferData(buffer, key, iv) {
95
95
  /** @type{Uint8Array[]} */
@@ -627,6 +627,10 @@ export function createRpcServerHelper(param) {
627
627
  * writable: WritableStream<Uint8Array>;
628
628
  * readable: ReadableStream<Uint8Array>;
629
629
  * apiInvoke: (fnName: string, args: object[]) => Promise<object>;
630
+ * transform:()=>{
631
+ * readable: ReadableStream<Uint8Array<ArrayBufferLike>>;
632
+ * witeable: WritableStream<Uint8Array<ArrayBufferLike>>;
633
+ * }
630
634
  * }} RPC_HELPER_CLIENT
631
635
  */
632
636
 
@@ -710,8 +714,15 @@ export function createRpcClientHelper(param) {
710
714
  }
711
715
  }
712
716
 
717
+ function transform() {
718
+ let decode = createDecodeStream(rpc_key_iv)
719
+ let encode = createEncodeStream(rpc_key_iv)
720
+ decode.readable.pipeTo(encode.writable)
721
+ return { readable: encode.readable, witeable: decode.writable }
722
+ }
723
+
713
724
  /** @type{RPC_HELPER_CLIENT} */
714
- let ret = { writable: decode.writable, readable: encode.readable, apiInvoke }
725
+ let ret = { writable: decode.writable, readable: encode.readable, apiInvoke, transform }
715
726
  return ret
716
727
  }
717
728
 
@@ -790,20 +801,23 @@ export function createRpcClientHttp(param) {
790
801
  let helper = createRpcClientHelper({ rpcKey: param.rpcKey })
791
802
  let writer = helper.writable.getWriter()
792
803
  helper.readable.pipeTo(new WritableStream({
793
- async write(chunk) {
794
- let res = await fetch(param.url, {
804
+ write(chunk) {
805
+ fetch(param.url, {
795
806
  method: 'POST',
796
807
  signal: param.signal,
797
808
  body: chunk,
798
- })
799
- if (param.intercept) {
800
- param.intercept(res)
801
- }
802
- res.body.pipeTo(new WritableStream({
803
- async write(chunk) {
804
- await writer.write(chunk)
809
+ }).then(res => {
810
+ if (param.intercept) {
811
+ param.intercept(res)
805
812
  }
806
- })).catch((err) => console.error('createRpcClientHttp fetch error', err.message))
813
+ let transform = helper.transform()
814
+ res.body.pipeTo(transform.witeable).catch(e => console.error(e))
815
+ transform.readable.pipeTo(new WritableStream({
816
+ async write(chunk) {
817
+ await writer.write(chunk)
818
+ }
819
+ })).catch((e) => console.error(e))
820
+ }).catch(e => console.error(e))
807
821
  }
808
822
  })).catch((err) => console.error('createRpcClientHttp', err.message))
809
823
  return createRPCProxy(helper.apiInvoke)
package/src/lib.test.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { test } from 'node:test'
2
- import { deepStrictEqual, strictEqual } from 'node:assert'
2
+ import { deepStrictEqual, ok, strictEqual } from 'node:assert'
3
3
  import { createRpcClientHttp, createRpcClientWebSocket, sleep, Uint8Array_from } from './lib.js'
4
4
  import { createServer } from 'node:http'
5
5
  import { WebSocketServer } from 'ws'
@@ -7,6 +7,69 @@ import Koa from 'koa'
7
7
  import Router from 'koa-router'
8
8
  import { createRpcServerKoaRouter, createRpcServerWebSocket } from './server.js'
9
9
 
10
+ test('basic', async () => {
11
+ // node --test-name-pattern="^basic$" src/lib.test.js
12
+
13
+ // server
14
+ const app = new Koa()
15
+ const router = new Router()
16
+ app.use(router.routes())
17
+ app.use(router.allowedMethods())
18
+ let server = createServer(app.callback()).listen(9000)
19
+
20
+ class RpcApi {
21
+ /**
22
+ *
23
+ * @param {string} string
24
+ * @param {Uint8Array} buffer
25
+ * @param {Object} object
26
+ * @param {null} _null
27
+ * @param {undefined} _undefined
28
+ * @param {object[]} array
29
+ * @param {(arg1:string,arg2:number)=>void} callback
30
+ */
31
+ async hello(string, buffer, object, _null, _undefined, array, callback) {
32
+ for (let i = 0; i < 3; i++) {
33
+ callback('progress : ', i)
34
+ await new Promise((resolve) => setTimeout(resolve, 1000))
35
+ }
36
+ return [
37
+ `${typeof string}-${typeof buffer}-${typeof object}-${typeof _null}-${typeof _undefined}-${typeof array}`,
38
+ new Uint8Array(3),
39
+ { a: 1, b: 2, c: 3 },
40
+ 1,
41
+ true,
42
+ undefined,
43
+ [1, 2, 3, 4],
44
+ ]
45
+ }
46
+ }
47
+
48
+ const extension = new RpcApi()
49
+
50
+ createRpcServerKoaRouter({
51
+ path: '/rpc/abc',
52
+ router: router,
53
+ extension: extension,
54
+ })
55
+
56
+
57
+ // client
58
+
59
+ /** @type{RpcApi} */
60
+ const rpc = createRpcClientHttp({
61
+ // url: `/rpc/abc`, // in same site html page
62
+ url: `http://127.0.0.1:9000/rpc/abc`, // others
63
+ })
64
+
65
+ let ret = await rpc.hello('123', new Uint8Array(3), { q: 2, w: 3, e: 4 }, null, undefined, [1, 2, 3, 4], (message, num) => {
66
+ console.info('callback', message, num)
67
+ })
68
+ console.info(ret)
69
+ server.close()
70
+
71
+ })
72
+
10
73
  test('测试RPC调用-WebSocket', async () => {
11
74
  // node --test-name-pattern="^测试RPC调用-WebSocket$" src/lib.test.js
12
75
 
@@ -130,6 +193,10 @@ test('测试RPC调用-KoaRouter', async () => {
130
193
  },
131
194
  void: async function (/** @type {string} */ name,/** @type {Uint8Array} */ buffer) {
132
195
  console.info('call void')
196
+ },
197
+ longTimeBlock: async function () {
198
+ await sleep(1000)
199
+ return 'finished'
133
200
  }
134
201
  }
135
202
 
@@ -188,6 +255,20 @@ test('测试RPC调用-KoaRouter', async () => {
188
255
 
189
256
  let retvoid = await client.void('asdfghjkl', buffer)
190
257
  strictEqual(retvoid, undefined)
258
+
259
+ let startTime = performance.now()
260
+ let [time1, time2] = await Promise.all([
261
+ client.longTimeBlock().then(v => {
262
+ console.info('longTimeBlock', v)
263
+ return performance.now() - startTime
264
+ }),
265
+ client.hello('欣瑶').then(v => {
266
+ console.info('hello', v)
267
+ return performance.now() - startTime
268
+ })
269
+ ])
270
+ ok(time1 > 1000, `time1:${time1}`)
271
+ ok(time2 < 10, `time2:${time2}`)
191
272
  })
192
273
  console.info('over!')
193
274
  })