js-rpc2 2.4.0 → 2.4.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 +1 -1
- package/doc/chrome-extensions.md +132 -132
- package/doc/electron.md +137 -137
- package/doc/http.md +202 -0
- package/doc/other_environments.md +467 -0
- package/doc/websocket.md +223 -0
- package/doc/worker_threads.md +186 -186
- package/package.json +1 -1
- package/src/lib.js +4 -4
package/doc/websocket.md
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# WebSocket 使用文档
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
|
|
5
|
+
js-rpc 支持通过 WebSocket 协议进行 RPC 调用,提供了比 HTTP 更高效的双向通信能力。WebSocket 传输适用于需要实时通信、频繁交互或长时间连接的应用场景。
|
|
6
|
+
|
|
7
|
+
## 核心组件
|
|
8
|
+
|
|
9
|
+
### 服务器端
|
|
10
|
+
|
|
11
|
+
1. [createRpcServerWebSocket](../src/server.js#L37) - 创建 WebSocket RPC 服务器
|
|
12
|
+
2. [createRpcServerHelper](../src/lib.js#L467) - 创建 RPC 服务器助手(内部使用)
|
|
13
|
+
|
|
14
|
+
### 客户端
|
|
15
|
+
|
|
16
|
+
1. [createRpcClientWebSocket](../src/lib.js#L656) - 创建 WebSocket RPC 客户端
|
|
17
|
+
|
|
18
|
+
## 完整示例
|
|
19
|
+
|
|
20
|
+
### 1. 服务器端代码 (server.js)
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
import { createServer } from 'http'
|
|
24
|
+
import { WebSocketServer } from 'ws'
|
|
25
|
+
import { createRpcServerWebSocket } from 'js-rpc2/src/server.js'
|
|
26
|
+
|
|
27
|
+
// 创建 HTTP 服务器
|
|
28
|
+
const server = createServer()
|
|
29
|
+
|
|
30
|
+
// 创建 WebSocket 服务器
|
|
31
|
+
const wss = new WebSocketServer({ server })
|
|
32
|
+
|
|
33
|
+
// 定义可远程调用的函数
|
|
34
|
+
class RpcApi {
|
|
35
|
+
/**
|
|
36
|
+
* 示例方法:带回调的异步函数
|
|
37
|
+
* @param {string} name - 名称参数
|
|
38
|
+
* @param {(data: string) => void} update - 回调函数,用于报告进度
|
|
39
|
+
*/
|
|
40
|
+
async hello(name, update) {
|
|
41
|
+
for (let i = 0; i < 5; i++) {
|
|
42
|
+
// 调用回调函数报告进度
|
|
43
|
+
update(`progress ${i}`)
|
|
44
|
+
await new Promise((resolve) => setTimeout(resolve, 500))
|
|
45
|
+
}
|
|
46
|
+
return `Hello, ${name}!`
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 示例方法:处理二进制数据
|
|
51
|
+
* @param {Uint8Array} buffer - 二进制数据
|
|
52
|
+
*/
|
|
53
|
+
async processBuffer(buffer) {
|
|
54
|
+
// 模拟处理过程
|
|
55
|
+
await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
56
|
+
// 返回处理后的数据
|
|
57
|
+
return new Uint8Array(buffer.map(b => b * 2))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 示例方法:实时数据推送
|
|
62
|
+
* @param {(data: object) => void} callback - 数据推送回调
|
|
63
|
+
*/
|
|
64
|
+
async subscribeToData(callback) {
|
|
65
|
+
// 模拟实时数据推送
|
|
66
|
+
for (let i = 0; i < 10; i++) {
|
|
67
|
+
await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
68
|
+
callback({
|
|
69
|
+
timestamp: Date.now(),
|
|
70
|
+
value: Math.random(),
|
|
71
|
+
index: i
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
return 'Subscription ended'
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 创建 API 实例
|
|
79
|
+
const extension = new RpcApi()
|
|
80
|
+
|
|
81
|
+
// 创建 RPC 服务器
|
|
82
|
+
createRpcServerWebSocket({
|
|
83
|
+
path: '/rpc', // RPC 服务路径
|
|
84
|
+
wss: wss, // WebSocket 服务器实例
|
|
85
|
+
extension: extension, // 可调用的函数集合
|
|
86
|
+
rpcKey: 'optional-secret-key' // 可选的安全密钥
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
// 启动服务器
|
|
90
|
+
server.listen(9000, () => {
|
|
91
|
+
console.log('WebSocket RPC server listening on port 9000')
|
|
92
|
+
})
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 2. 客户端代码 (client.js)
|
|
96
|
+
|
|
97
|
+
```js
|
|
98
|
+
import { createRpcClientWebSocket } from 'js-rpc2/src/client.js'
|
|
99
|
+
|
|
100
|
+
// 创建 AbortController 用于控制连接
|
|
101
|
+
const ac = new AbortController()
|
|
102
|
+
|
|
103
|
+
// 创建 RPC 客户端
|
|
104
|
+
/** @type{RpcApi} */
|
|
105
|
+
const rpc = createRpcClientWebSocket({
|
|
106
|
+
url: 'ws://127.0.0.1:9000/rpc', // WebSocket RPC 服务地址
|
|
107
|
+
rpcKey: 'optional-secret-key', // 可选的安全密钥(需与服务端一致)
|
|
108
|
+
signal: ac.signal // 用于控制连接的信号
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
// 使用示例
|
|
112
|
+
async function example() {
|
|
113
|
+
try {
|
|
114
|
+
// 调用带回调的异步函数
|
|
115
|
+
console.log('Calling hello with progress updates...')
|
|
116
|
+
const result = await rpc.hello('WebSocket User', (progress) => {
|
|
117
|
+
console.log('Progress update:', progress)
|
|
118
|
+
})
|
|
119
|
+
console.log('Hello result:', result)
|
|
120
|
+
|
|
121
|
+
// 调用处理二进制数据的函数
|
|
122
|
+
console.log('Processing binary data...')
|
|
123
|
+
const buffer = new Uint8Array([1, 2, 3, 4, 5])
|
|
124
|
+
const processedBuffer = await rpc.processBuffer(buffer)
|
|
125
|
+
console.log('Processed buffer:', processedBuffer)
|
|
126
|
+
|
|
127
|
+
// 订阅实时数据
|
|
128
|
+
console.log('Subscribing to real-time data...')
|
|
129
|
+
const subscriptionResult = await rpc.subscribeToData((data) => {
|
|
130
|
+
console.log('Real-time data:', data)
|
|
131
|
+
})
|
|
132
|
+
console.log('Subscription result:', subscriptionResult)
|
|
133
|
+
|
|
134
|
+
} catch (error) {
|
|
135
|
+
console.error('RPC call failed:', error)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// 执行示例
|
|
140
|
+
example()
|
|
141
|
+
|
|
142
|
+
// 在需要时断开连接
|
|
143
|
+
// ac.abort()
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## API 说明
|
|
147
|
+
|
|
148
|
+
### 服务器端 API
|
|
149
|
+
|
|
150
|
+
#### createRpcServerWebSocket
|
|
151
|
+
|
|
152
|
+
创建 WebSocket RPC 服务器。
|
|
153
|
+
|
|
154
|
+
```js
|
|
155
|
+
/**
|
|
156
|
+
* @param {{
|
|
157
|
+
* path: string;
|
|
158
|
+
* wss: WebSocketServer;
|
|
159
|
+
* rpcKey:string;
|
|
160
|
+
* extension: {asyncLocalStorage:AsyncLocalStorage<IncomingMessage>;};
|
|
161
|
+
* logger?:(msg:string)=>void;
|
|
162
|
+
* }} param
|
|
163
|
+
*/
|
|
164
|
+
export function createRpcServerWebSocket(param)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
参数说明:
|
|
168
|
+
- `path`: RPC 服务的路径,用于区分不同的服务
|
|
169
|
+
- `wss`: WebSocketServer 实例
|
|
170
|
+
- `rpcKey`: 可选的安全密钥,用于验证客户端连接
|
|
171
|
+
- `extension`: 包含可远程调用函数的对象
|
|
172
|
+
- `logger`: 可选的日志函数
|
|
173
|
+
|
|
174
|
+
### 客户端 API
|
|
175
|
+
|
|
176
|
+
#### createRpcClientWebSocket
|
|
177
|
+
|
|
178
|
+
创建 WebSocket RPC 客户端。
|
|
179
|
+
|
|
180
|
+
```js
|
|
181
|
+
/**
|
|
182
|
+
* @param {{
|
|
183
|
+
* url:string;
|
|
184
|
+
* rpcKey:string;
|
|
185
|
+
* signal:AbortSignal;
|
|
186
|
+
* intercept?:(e:Event)=>void;
|
|
187
|
+
* }} param
|
|
188
|
+
*/
|
|
189
|
+
export function createRpcClientWebSocket(param)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
参数说明:
|
|
193
|
+
- `url`: WebSocket RPC 服务的完整 URL
|
|
194
|
+
- `rpcKey`: 可选的安全密钥,需与服务端一致
|
|
195
|
+
- `signal`: AbortSignal,用于控制连接的生命周期
|
|
196
|
+
- `intercept`: 可选的事件拦截函数
|
|
197
|
+
|
|
198
|
+
## 特性
|
|
199
|
+
|
|
200
|
+
1. **双向通信**: WebSocket 提供全双工通信,服务器也可以主动向客户端推送数据
|
|
201
|
+
2. **实时性**: 低延迟通信,适用于实时应用
|
|
202
|
+
3. **连接保持**: 长连接减少重复握手开销
|
|
203
|
+
4. **类型安全**: 通过 JSDoc 注解提供完整的类型支持
|
|
204
|
+
5. **异步回调**: 支持在远程调用过程中传递回调函数
|
|
205
|
+
6. **二进制数据**: 原生支持 Uint8Array 等二进制数据类型
|
|
206
|
+
7. **自动重连**: 客户端具备自动重连机制
|
|
207
|
+
8. **错误处理**: 完善的错误处理和传播机制
|
|
208
|
+
|
|
209
|
+
## 使用场景
|
|
210
|
+
|
|
211
|
+
1. **实时应用**: 聊天应用、实时游戏、协作编辑等
|
|
212
|
+
2. **数据推送**: 实时数据监控、股票价格更新等
|
|
213
|
+
3. **频繁交互**: 需要频繁通信的应用,避免 HTTP 请求的开销
|
|
214
|
+
4. **长时间连接**: 需要保持连接状态的应用
|
|
215
|
+
|
|
216
|
+
## 注意事项
|
|
217
|
+
|
|
218
|
+
1. WebSocket 连接需要正确处理断开和重连逻辑
|
|
219
|
+
2. 服务器需要合理管理并发连接数
|
|
220
|
+
3. 注意处理网络异常和超时情况
|
|
221
|
+
4. 对于大规模部署,考虑使用负载均衡器
|
|
222
|
+
5. 安全方面,确保使用 WSS(WebSocket Secure)进行加密传输
|
|
223
|
+
6. 在防火墙环境中,确保 WebSocket 端口未被阻止
|
package/doc/worker_threads.md
CHANGED
|
@@ -1,187 +1,187 @@
|
|
|
1
|
-
# 在 Node.js Worker Threads 中使用 js-rpc
|
|
2
|
-
|
|
3
|
-
Node.js Worker Threads 是一种在 Node.js 中实现并行处理的机制,js-rpc 提供了在主线程和 Worker 线程之间进行 RPC 调用的能力。
|
|
4
|
-
|
|
5
|
-
## 概述
|
|
6
|
-
|
|
7
|
-
js-rpc 在 Node.js Worker Threads 中的使用主要包括两个部分:
|
|
8
|
-
1. 在 Worker 线程中创建 RPC 服务器:使用 [createRpcServerNodeJSWorker](../src/lib.js#L993)
|
|
9
|
-
2. 在主线程中创建 RPC 客户端:使用 [createRpcClientNodeJSWorker](../src/lib.js#L1013)
|
|
10
|
-
|
|
11
|
-
## 完整示例
|
|
12
|
-
|
|
13
|
-
### 1. Worker 线程代码 (worker.js)
|
|
14
|
-
|
|
15
|
-
```js
|
|
16
|
-
// 导入必要的模块
|
|
17
|
-
import { parentPort } from 'worker_threads'
|
|
18
|
-
import { createRpcServerNodeJSWorker } from 'js-rpc2/src/lib.js'
|
|
19
|
-
|
|
20
|
-
// 定义可被远程调用的函数
|
|
21
|
-
async function readClipboard() {
|
|
22
|
-
// 实现读取剪贴板的逻辑
|
|
23
|
-
// 这里只是示例,实际实现取决于你的需求
|
|
24
|
-
return 'clipboard content'
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async function writeClipboard(data) {
|
|
28
|
-
// 实现写入剪贴板的逻辑
|
|
29
|
-
console.log('Writing to clipboard:', data)
|
|
30
|
-
return true
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async function writeClipboardText(text) {
|
|
34
|
-
// 实现写入文本到剪贴板的逻辑
|
|
35
|
-
console.log('Writing text to clipboard:', text)
|
|
36
|
-
return true
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async function readClipboardText() {
|
|
40
|
-
// 实现读取剪贴板文本的逻辑
|
|
41
|
-
return 'clipboard text'
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async function readClipboardHtml() {
|
|
45
|
-
// 实现读取剪贴板 HTML 内容的逻辑
|
|
46
|
-
return '<p>clipboard html</p>'
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async function readClipboardImage() {
|
|
50
|
-
// 实现读取剪贴板图片的逻辑
|
|
51
|
-
return new Uint8Array([1, 2, 3, 4]) // 示例二进制数据
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// 将所有函数导出为一个 API 对象
|
|
55
|
-
export const ExtensionApi = {
|
|
56
|
-
readClipboard,
|
|
57
|
-
writeClipboard,
|
|
58
|
-
writeClipboardText,
|
|
59
|
-
readClipboardText,
|
|
60
|
-
readClipboardHtml,
|
|
61
|
-
readClipboardImage,
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// 创建 RPC 服务器
|
|
65
|
-
createRpcServerNodeJSWorker({
|
|
66
|
-
parentPort,
|
|
67
|
-
extension: ExtensionApi,
|
|
68
|
-
logger: (msg) => console.log('[Worker]', msg) // 可选的日志记录器
|
|
69
|
-
})
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### 2. 主线程代码 (main.js)
|
|
73
|
-
|
|
74
|
-
```js
|
|
75
|
-
// 导入必要的模块
|
|
76
|
-
import { createRpcClientNodeJSWorker } from 'js-rpc2/src/lib.js'
|
|
77
|
-
import { Worker } from 'worker_threads'
|
|
78
|
-
|
|
79
|
-
// 创建 Worker 实例
|
|
80
|
-
export const worker = new Worker(new URL('./worker.js', import.meta.url))
|
|
81
|
-
|
|
82
|
-
// 创建 RPC 客户端
|
|
83
|
-
/** @type{ExtensionApi} */
|
|
84
|
-
const rpc = createRpcClientNodeJSWorker({ worker: worker })
|
|
85
|
-
|
|
86
|
-
// 取消 Worker 的引用,允许程序在没有其他任务时退出
|
|
87
|
-
worker.unref()
|
|
88
|
-
|
|
89
|
-
// 包装远程调用函数
|
|
90
|
-
export async function readClipboard() {
|
|
91
|
-
return await rpc.readClipboard()
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* 写入剪贴板内容
|
|
96
|
-
* @param {'text'|'richtext'|'image'} type - 数据类型
|
|
97
|
-
* @param {string|Buffer} data - 要写入的数据
|
|
98
|
-
*/
|
|
99
|
-
export async function writeClipboard(type, data) {
|
|
100
|
-
return await rpc.writeClipboard(type, data)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* 写入文本到剪贴板
|
|
105
|
-
* @param {string} text - 要写入的文本
|
|
106
|
-
*/
|
|
107
|
-
export async function writeClipboardText(text) {
|
|
108
|
-
return rpc.writeClipboardText(text)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export async function readClipboardText() {
|
|
112
|
-
return rpc.readClipboardText()
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export async function readClipboardHtml() {
|
|
116
|
-
return rpc.readClipboardHtml()
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export async function readClipboardImage() {
|
|
120
|
-
return rpc.readClipboardImage()
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// 使用示例
|
|
124
|
-
async function example() {
|
|
125
|
-
// 调用远程函数
|
|
126
|
-
const text = await readClipboardText()
|
|
127
|
-
console.log('Clipboard text:', text)
|
|
128
|
-
|
|
129
|
-
await writeClipboardText('Hello from main thread!')
|
|
130
|
-
|
|
131
|
-
const image = await readClipboardImage()
|
|
132
|
-
console.log('Clipboard image size:', image.length)
|
|
133
|
-
}
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
## API 说明
|
|
137
|
-
|
|
138
|
-
### createRpcServerNodeJSWorker
|
|
139
|
-
|
|
140
|
-
在 Worker 线程中创建 RPC 服务器。
|
|
141
|
-
|
|
142
|
-
```js
|
|
143
|
-
/**
|
|
144
|
-
* @param {{
|
|
145
|
-
* parentPort: NodeJSMessagePort;
|
|
146
|
-
* extension: Object;
|
|
147
|
-
* logger?:(msg:string)=>void;
|
|
148
|
-
* }} param
|
|
149
|
-
*/
|
|
150
|
-
export function createRpcServerNodeJSWorker(param)
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
参数说明:
|
|
154
|
-
- `parentPort`: Worker 线程的 parentPort 对象,用于与主线程通信
|
|
155
|
-
- `extension`: 包含可被远程调用函数的对象
|
|
156
|
-
- `logger`: 可选的日志记录函数
|
|
157
|
-
|
|
158
|
-
### createRpcClientNodeJSWorker
|
|
159
|
-
|
|
160
|
-
在主线程中创建 RPC 客户端。
|
|
161
|
-
|
|
162
|
-
```js
|
|
163
|
-
/**
|
|
164
|
-
* @param {{
|
|
165
|
-
* worker:NodeJSWorker;
|
|
166
|
-
* }} param
|
|
167
|
-
*/
|
|
168
|
-
export function createRpcClientNodeJSWorker(param)
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
参数说明:
|
|
172
|
-
- `worker`: Worker 实例
|
|
173
|
-
|
|
174
|
-
## 特性
|
|
175
|
-
|
|
176
|
-
1. **透明的远程调用**:在主线程中调用 Worker 中的函数就像调用本地函数一样简单
|
|
177
|
-
2. **支持异步函数**:所有远程函数都可以是异步的
|
|
178
|
-
3. **参数和返回值序列化**:自动处理参数和返回值的序列化/反序列化
|
|
179
|
-
4. **类型安全**:通过 JSDoc 注解提供完整的类型支持
|
|
180
|
-
5. **错误处理**:远程函数抛出的错误会正确传播到调用方
|
|
181
|
-
|
|
182
|
-
## 注意事项
|
|
183
|
-
|
|
184
|
-
1. 确保 Worker 线程中的函数是可序列化的
|
|
185
|
-
2. 大数据传输可能影响性能,考虑使用流式传输
|
|
186
|
-
3. 避免在远程函数中使用闭包引用 Worker 外部的变量
|
|
1
|
+
# 在 Node.js Worker Threads 中使用 js-rpc
|
|
2
|
+
|
|
3
|
+
Node.js Worker Threads 是一种在 Node.js 中实现并行处理的机制,js-rpc 提供了在主线程和 Worker 线程之间进行 RPC 调用的能力。
|
|
4
|
+
|
|
5
|
+
## 概述
|
|
6
|
+
|
|
7
|
+
js-rpc 在 Node.js Worker Threads 中的使用主要包括两个部分:
|
|
8
|
+
1. 在 Worker 线程中创建 RPC 服务器:使用 [createRpcServerNodeJSWorker](../src/lib.js#L993)
|
|
9
|
+
2. 在主线程中创建 RPC 客户端:使用 [createRpcClientNodeJSWorker](../src/lib.js#L1013)
|
|
10
|
+
|
|
11
|
+
## 完整示例
|
|
12
|
+
|
|
13
|
+
### 1. Worker 线程代码 (worker.js)
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
// 导入必要的模块
|
|
17
|
+
import { parentPort } from 'worker_threads'
|
|
18
|
+
import { createRpcServerNodeJSWorker } from 'js-rpc2/src/lib.js'
|
|
19
|
+
|
|
20
|
+
// 定义可被远程调用的函数
|
|
21
|
+
async function readClipboard() {
|
|
22
|
+
// 实现读取剪贴板的逻辑
|
|
23
|
+
// 这里只是示例,实际实现取决于你的需求
|
|
24
|
+
return 'clipboard content'
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function writeClipboard(data) {
|
|
28
|
+
// 实现写入剪贴板的逻辑
|
|
29
|
+
console.log('Writing to clipboard:', data)
|
|
30
|
+
return true
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function writeClipboardText(text) {
|
|
34
|
+
// 实现写入文本到剪贴板的逻辑
|
|
35
|
+
console.log('Writing text to clipboard:', text)
|
|
36
|
+
return true
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function readClipboardText() {
|
|
40
|
+
// 实现读取剪贴板文本的逻辑
|
|
41
|
+
return 'clipboard text'
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function readClipboardHtml() {
|
|
45
|
+
// 实现读取剪贴板 HTML 内容的逻辑
|
|
46
|
+
return '<p>clipboard html</p>'
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function readClipboardImage() {
|
|
50
|
+
// 实现读取剪贴板图片的逻辑
|
|
51
|
+
return new Uint8Array([1, 2, 3, 4]) // 示例二进制数据
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 将所有函数导出为一个 API 对象
|
|
55
|
+
export const ExtensionApi = {
|
|
56
|
+
readClipboard,
|
|
57
|
+
writeClipboard,
|
|
58
|
+
writeClipboardText,
|
|
59
|
+
readClipboardText,
|
|
60
|
+
readClipboardHtml,
|
|
61
|
+
readClipboardImage,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 创建 RPC 服务器
|
|
65
|
+
createRpcServerNodeJSWorker({
|
|
66
|
+
parentPort,
|
|
67
|
+
extension: ExtensionApi,
|
|
68
|
+
logger: (msg) => console.log('[Worker]', msg) // 可选的日志记录器
|
|
69
|
+
})
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 2. 主线程代码 (main.js)
|
|
73
|
+
|
|
74
|
+
```js
|
|
75
|
+
// 导入必要的模块
|
|
76
|
+
import { createRpcClientNodeJSWorker } from 'js-rpc2/src/lib.js'
|
|
77
|
+
import { Worker } from 'worker_threads'
|
|
78
|
+
|
|
79
|
+
// 创建 Worker 实例
|
|
80
|
+
export const worker = new Worker(new URL('./worker.js', import.meta.url))
|
|
81
|
+
|
|
82
|
+
// 创建 RPC 客户端
|
|
83
|
+
/** @type{ExtensionApi} */
|
|
84
|
+
const rpc = createRpcClientNodeJSWorker({ worker: worker })
|
|
85
|
+
|
|
86
|
+
// 取消 Worker 的引用,允许程序在没有其他任务时退出
|
|
87
|
+
worker.unref()
|
|
88
|
+
|
|
89
|
+
// 包装远程调用函数
|
|
90
|
+
export async function readClipboard() {
|
|
91
|
+
return await rpc.readClipboard()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* 写入剪贴板内容
|
|
96
|
+
* @param {'text'|'richtext'|'image'} type - 数据类型
|
|
97
|
+
* @param {string|Buffer} data - 要写入的数据
|
|
98
|
+
*/
|
|
99
|
+
export async function writeClipboard(type, data) {
|
|
100
|
+
return await rpc.writeClipboard(type, data)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* 写入文本到剪贴板
|
|
105
|
+
* @param {string} text - 要写入的文本
|
|
106
|
+
*/
|
|
107
|
+
export async function writeClipboardText(text) {
|
|
108
|
+
return rpc.writeClipboardText(text)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export async function readClipboardText() {
|
|
112
|
+
return rpc.readClipboardText()
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export async function readClipboardHtml() {
|
|
116
|
+
return rpc.readClipboardHtml()
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export async function readClipboardImage() {
|
|
120
|
+
return rpc.readClipboardImage()
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 使用示例
|
|
124
|
+
async function example() {
|
|
125
|
+
// 调用远程函数
|
|
126
|
+
const text = await readClipboardText()
|
|
127
|
+
console.log('Clipboard text:', text)
|
|
128
|
+
|
|
129
|
+
await writeClipboardText('Hello from main thread!')
|
|
130
|
+
|
|
131
|
+
const image = await readClipboardImage()
|
|
132
|
+
console.log('Clipboard image size:', image.length)
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## API 说明
|
|
137
|
+
|
|
138
|
+
### createRpcServerNodeJSWorker
|
|
139
|
+
|
|
140
|
+
在 Worker 线程中创建 RPC 服务器。
|
|
141
|
+
|
|
142
|
+
```js
|
|
143
|
+
/**
|
|
144
|
+
* @param {{
|
|
145
|
+
* parentPort: NodeJSMessagePort;
|
|
146
|
+
* extension: Object;
|
|
147
|
+
* logger?:(msg:string)=>void;
|
|
148
|
+
* }} param
|
|
149
|
+
*/
|
|
150
|
+
export function createRpcServerNodeJSWorker(param)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
参数说明:
|
|
154
|
+
- `parentPort`: Worker 线程的 parentPort 对象,用于与主线程通信
|
|
155
|
+
- `extension`: 包含可被远程调用函数的对象
|
|
156
|
+
- `logger`: 可选的日志记录函数
|
|
157
|
+
|
|
158
|
+
### createRpcClientNodeJSWorker
|
|
159
|
+
|
|
160
|
+
在主线程中创建 RPC 客户端。
|
|
161
|
+
|
|
162
|
+
```js
|
|
163
|
+
/**
|
|
164
|
+
* @param {{
|
|
165
|
+
* worker:NodeJSWorker;
|
|
166
|
+
* }} param
|
|
167
|
+
*/
|
|
168
|
+
export function createRpcClientNodeJSWorker(param)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
参数说明:
|
|
172
|
+
- `worker`: Worker 实例
|
|
173
|
+
|
|
174
|
+
## 特性
|
|
175
|
+
|
|
176
|
+
1. **透明的远程调用**:在主线程中调用 Worker 中的函数就像调用本地函数一样简单
|
|
177
|
+
2. **支持异步函数**:所有远程函数都可以是异步的
|
|
178
|
+
3. **参数和返回值序列化**:自动处理参数和返回值的序列化/反序列化
|
|
179
|
+
4. **类型安全**:通过 JSDoc 注解提供完整的类型支持
|
|
180
|
+
5. **错误处理**:远程函数抛出的错误会正确传播到调用方
|
|
181
|
+
|
|
182
|
+
## 注意事项
|
|
183
|
+
|
|
184
|
+
1. 确保 Worker 线程中的函数是可序列化的
|
|
185
|
+
2. 大数据传输可能影响性能,考虑使用流式传输
|
|
186
|
+
3. 避免在远程函数中使用闭包引用 Worker 外部的变量
|
|
187
187
|
4. Worker 线程在没有任务时会自动退出,如需保持运行请适当管理引用
|
package/package.json
CHANGED
package/src/lib.js
CHANGED
|
@@ -696,13 +696,13 @@ export function createRpcClientWebSocket(param) {
|
|
|
696
696
|
signal.resolve()
|
|
697
697
|
})
|
|
698
698
|
ws.addEventListener('error', (e) => {
|
|
699
|
-
if (param.intercept) {
|
|
700
|
-
param.intercept(e)
|
|
701
|
-
}
|
|
702
699
|
console.error('createRpcClientWebSocket createWebSocket ws error', e)
|
|
703
700
|
promise.resolve()
|
|
704
701
|
})
|
|
705
|
-
ws.addEventListener('close', () => {
|
|
702
|
+
ws.addEventListener('close', (e) => {
|
|
703
|
+
if (param.intercept) {
|
|
704
|
+
param.intercept(e)
|
|
705
|
+
}
|
|
706
706
|
console.error('createRpcClientWebSocket createWebSocket ws close')
|
|
707
707
|
promise.resolve()
|
|
708
708
|
})
|