@lynker-desktop/electron-ipc 0.0.9-alpha.49 → 0.0.9-alpha.50
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/esm/main/index.d.ts +1 -1
- package/esm/main/index.d.ts.map +1 -1
- package/esm/main/index.js +91 -32
- package/esm/main/index.js.map +1 -1
- package/main/index.d.ts +1 -1
- package/main/index.d.ts.map +1 -1
- package/main/index.js +91 -32
- package/main/index.js.map +1 -1
- package/package.json +2 -2
package/esm/main/index.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ declare class MainIPC {
|
|
|
25
25
|
* - 监听 `${channel}-reply-${requestId}` 事件,确保只接收对应请求的回复
|
|
26
26
|
* - 发送请求时包含 requestId,让处理器知道如何回复
|
|
27
27
|
*/
|
|
28
|
-
invokeMain(channel: string, ...args: any[]): Promise<
|
|
28
|
+
invokeMain(channel: string, ...args: any[]): Promise<any>;
|
|
29
29
|
/**
|
|
30
30
|
* 处理主进程发送过来的消息
|
|
31
31
|
* 持续监听指定通道的消息
|
package/esm/main/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/main/index.ts"],"names":[],"mappings":"AAIA,eAAO,IAAI,aAAa,SAAQ,CAAC;AAEjC;;;;;;;;GAQG;AACH,cAAM,OAAO;IACZ,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAA;IACxB,OAAO,CAAC,YAAY,CAAmC;;IAUtD;;;;;;;;;;;;OAYG;IACE,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/main/index.ts"],"names":[],"mappings":"AAIA,eAAO,IAAI,aAAa,SAAQ,CAAC;AAEjC;;;;;;;;GAQG;AACH,cAAM,OAAO;IACZ,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAA;IACxB,OAAO,CAAC,YAAY,CAAmC;;IAUtD;;;;;;;;;;;;OAYG;IACE,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IA8B9D;;;;;;;;;;;OAWG;IACJ,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC;;;IAYpE;;;;;;;;;;;;;;OAcG;IACJ,cAAc,CAAC,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IA+C7F;;;;;;;;;;;;;;KAcC;IACJ,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IAuD/D;;;;;;;;;;;;;OAaG;IACJ,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC;;;IAyCxE;;;;;;;;;OASG;IACJ,YAAY;CAkEZ;AAED;;;GAGG;AAEH,eAAO,MAAM,OAAO,EAAE,OAAgH,CAAC;AAEvI;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,WAWtB,CAAA"}
|
package/esm/main/index.js
CHANGED
|
@@ -35,11 +35,27 @@ class MainIPC {
|
|
|
35
35
|
* - 发送请求时包含 requestId,让处理器知道如何回复
|
|
36
36
|
*/
|
|
37
37
|
async invokeMain(channel, ...args) {
|
|
38
|
-
return new Promise(resolve => {
|
|
38
|
+
return new Promise((resolve, reject) => {
|
|
39
39
|
const requestId = getRandomUUID();
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
const replyChannel = `${channel}-reply-${requestId}`;
|
|
41
|
+
let isResolved = false;
|
|
42
|
+
const replyHandler = (result) => {
|
|
43
|
+
if (!isResolved) {
|
|
44
|
+
isResolved = true;
|
|
45
|
+
this.eventEmitter.removeListener(replyChannel, replyHandler);
|
|
46
|
+
clearTimeout(timeoutId);
|
|
47
|
+
resolve(result);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
this.eventEmitter.once(replyChannel, replyHandler);
|
|
51
|
+
// 添加超时机制,确保监听器最终会被清理
|
|
52
|
+
const timeoutId = setTimeout(() => {
|
|
53
|
+
if (!isResolved) {
|
|
54
|
+
isResolved = true;
|
|
55
|
+
this.eventEmitter.removeListener(replyChannel, replyHandler);
|
|
56
|
+
reject(new Error(`IPC request timeout: ${channel} (30s)`));
|
|
57
|
+
}
|
|
58
|
+
}, 30000); // 30秒超时
|
|
43
59
|
this.eventEmitter.emit(channel, requestId, ...args);
|
|
44
60
|
});
|
|
45
61
|
}
|
|
@@ -82,12 +98,33 @@ class MainIPC {
|
|
|
82
98
|
* - 等待渲染进程加载完成后再发送消息,确保消息能够被正确接收
|
|
83
99
|
*/
|
|
84
100
|
invokeRenderer(webContents, channel, ...args) {
|
|
85
|
-
return new Promise(resolve => {
|
|
101
|
+
return new Promise((resolve, reject) => {
|
|
86
102
|
const requestId = getRandomUUID();
|
|
103
|
+
const replyChannel = `${channel}-reply-${requestId}`;
|
|
104
|
+
let isResolved = false;
|
|
87
105
|
const sendMessage = () => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
106
|
+
// 检查 webContents 是否已销毁
|
|
107
|
+
if (webContents.isDestroyed()) {
|
|
108
|
+
reject(new Error('WebContents has been destroyed'));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const replyHandler = (_event, result) => {
|
|
112
|
+
if (!isResolved) {
|
|
113
|
+
isResolved = true;
|
|
114
|
+
ipcMain.removeListener(replyChannel, replyHandler);
|
|
115
|
+
clearTimeout(timeoutId);
|
|
116
|
+
resolve(result);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
ipcMain.once(replyChannel, replyHandler);
|
|
120
|
+
// 添加超时机制,确保监听器最终会被清理
|
|
121
|
+
const timeoutId = setTimeout(() => {
|
|
122
|
+
if (!isResolved) {
|
|
123
|
+
isResolved = true;
|
|
124
|
+
ipcMain.removeListener(replyChannel, replyHandler);
|
|
125
|
+
reject(new Error(`IPC request timeout: ${channel} (30s)`));
|
|
126
|
+
}
|
|
127
|
+
}, 30000); // 30秒超时
|
|
91
128
|
webContents.send(channel, requestId, ...args);
|
|
92
129
|
};
|
|
93
130
|
// 等待渲染进程加载完成后再推送,否则会导致渲染进程收不到消息
|
|
@@ -126,15 +163,30 @@ class MainIPC {
|
|
|
126
163
|
return;
|
|
127
164
|
}
|
|
128
165
|
const responses = [];
|
|
166
|
+
const replyChannel = `${channel}-reply-${requestId}`;
|
|
167
|
+
// 只注册一个监听器,避免内存泄漏
|
|
168
|
+
// 使用 on 而不是 once,因为需要接收多个响应
|
|
169
|
+
const replyHandler = (_event, result) => {
|
|
170
|
+
responses.push(result);
|
|
171
|
+
responseCount++;
|
|
172
|
+
if (responseCount === totalWebContents) {
|
|
173
|
+
// 清理监听器
|
|
174
|
+
ipcMain.removeListener(replyChannel, replyHandler);
|
|
175
|
+
clearTimeout(timeoutId);
|
|
176
|
+
resolve(responses);
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
ipcMain.on(replyChannel, replyHandler);
|
|
180
|
+
// 添加超时机制,确保监听器最终会被清理
|
|
181
|
+
const timeoutId = setTimeout(() => {
|
|
182
|
+
ipcMain.removeListener(replyChannel, replyHandler);
|
|
183
|
+
if (responseCount < totalWebContents) {
|
|
184
|
+
// 超时后返回已收到的响应
|
|
185
|
+
resolve(responses);
|
|
186
|
+
}
|
|
187
|
+
}, 30000); // 30秒超时
|
|
129
188
|
webContents.getAllWebContents().forEach(webContent => {
|
|
130
189
|
const sendMessage = () => {
|
|
131
|
-
ipcMain.once(`${channel}-reply-${requestId}`, (_event, result) => {
|
|
132
|
-
responses.push(result);
|
|
133
|
-
responseCount++;
|
|
134
|
-
if (responseCount === totalWebContents) {
|
|
135
|
-
resolve(responses);
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
190
|
webContent.send(channel, requestId, ...args);
|
|
139
191
|
};
|
|
140
192
|
// 等待渲染进程加载完成后再推送,否则会导致渲染进程收不到消息
|
|
@@ -168,18 +220,17 @@ class MainIPC {
|
|
|
168
220
|
ipcMain.handle(channel, async (event, ...args) => {
|
|
169
221
|
try {
|
|
170
222
|
const timeout = () => {
|
|
171
|
-
return new Promise((
|
|
223
|
+
return new Promise((resolve, reject) => {
|
|
172
224
|
setTimeout(() => {
|
|
173
225
|
reject(new Error('请求超时'));
|
|
174
226
|
}, 1000 * 8); // 设定超时时间为8秒
|
|
175
227
|
});
|
|
176
228
|
};
|
|
177
229
|
const processing = () => {
|
|
178
|
-
return new Promise(async (
|
|
230
|
+
return new Promise(async (resolve, reject) => {
|
|
179
231
|
try {
|
|
180
232
|
const data = await handler(...args);
|
|
181
|
-
|
|
182
|
-
_(data);
|
|
233
|
+
resolve(data);
|
|
183
234
|
}
|
|
184
235
|
catch (error) {
|
|
185
236
|
reject(error);
|
|
@@ -192,14 +243,14 @@ class MainIPC {
|
|
|
192
243
|
return result; // 返回正常结果
|
|
193
244
|
}
|
|
194
245
|
catch (error) {
|
|
195
|
-
|
|
246
|
+
log('error', 'SDK handleRenderer error: ', `channel: ${channel}`, error);
|
|
196
247
|
// @ts-ignore
|
|
197
248
|
return error?.message; // 返回超时错误信息
|
|
198
249
|
}
|
|
199
250
|
});
|
|
200
251
|
}
|
|
201
252
|
catch (error) {
|
|
202
|
-
|
|
253
|
+
log('error', 'SDK handleRenderer error: ', error);
|
|
203
254
|
}
|
|
204
255
|
return {
|
|
205
256
|
cancel: () => {
|
|
@@ -218,8 +269,8 @@ class MainIPC {
|
|
|
218
269
|
* - __OpenCurrentWebContentDevTools__: 打开当前 WebContent 的开发者工具
|
|
219
270
|
*/
|
|
220
271
|
relayMessage() {
|
|
221
|
-
//
|
|
222
|
-
|
|
272
|
+
// 防止重复注册监听器:先移除再添加
|
|
273
|
+
const relayMessageHandler = (_event, { targetWebContentId, channel, requestId, args }) => {
|
|
223
274
|
log('log', 'relay-message', { targetWebContentId, channel, requestId, args });
|
|
224
275
|
if (targetWebContentId) {
|
|
225
276
|
// 转发到指定的渲染进程
|
|
@@ -234,9 +285,11 @@ class MainIPC {
|
|
|
234
285
|
webContent.send(channel, requestId, ...args);
|
|
235
286
|
});
|
|
236
287
|
}
|
|
237
|
-
}
|
|
288
|
+
};
|
|
289
|
+
ipcMain.removeListener('relay-message', relayMessageHandler);
|
|
290
|
+
ipcMain.on('relay-message', relayMessageHandler);
|
|
238
291
|
// 处理回复消息广播
|
|
239
|
-
|
|
292
|
+
const relayReplyHandler = (_event, { originalChannel, requestId, result }) => {
|
|
240
293
|
log('log', 'relay-reply', { originalChannel, requestId, result });
|
|
241
294
|
// 使用 requestId 确保回复发送给正确的请求
|
|
242
295
|
// 所有渲染进程都会接收 ${originalChannel}-reply-${requestId} 事件
|
|
@@ -244,22 +297,26 @@ class MainIPC {
|
|
|
244
297
|
webContents.getAllWebContents().forEach(webContent => {
|
|
245
298
|
webContent.send(`${originalChannel}-reply-${requestId}`, result);
|
|
246
299
|
});
|
|
247
|
-
}
|
|
300
|
+
};
|
|
301
|
+
ipcMain.removeListener('relay-reply', relayReplyHandler);
|
|
302
|
+
ipcMain.on('relay-reply', relayReplyHandler);
|
|
248
303
|
// 获取当前 WebContent ID 的通道
|
|
249
304
|
const getCurrentWebContentIdChannel = '__GetCurrentWebContentId__';
|
|
250
|
-
|
|
305
|
+
const getCurrentWebContentIdHandler = (_event) => {
|
|
251
306
|
try {
|
|
252
307
|
_event.frameId;
|
|
253
308
|
const webContentId = _event?.sender?.id;
|
|
254
309
|
_event.sender.send(`${getCurrentWebContentIdChannel}-reply`, webContentId);
|
|
255
310
|
}
|
|
256
311
|
catch (error) {
|
|
257
|
-
|
|
312
|
+
log('error', 'getCurrentWebContentId error:', error);
|
|
258
313
|
}
|
|
259
|
-
}
|
|
314
|
+
};
|
|
315
|
+
ipcMain.removeListener(getCurrentWebContentIdChannel, getCurrentWebContentIdHandler);
|
|
316
|
+
ipcMain.on(getCurrentWebContentIdChannel, getCurrentWebContentIdHandler);
|
|
260
317
|
// 打开当前 WebContent 开发者工具的通道
|
|
261
318
|
const openCurrentWebContentDevToolsChannel = '__OpenCurrentWebContentDevTools__';
|
|
262
|
-
|
|
319
|
+
const openCurrentWebContentDevToolsHandler = (_event) => {
|
|
263
320
|
try {
|
|
264
321
|
_event.frameId;
|
|
265
322
|
const webContentId = _event?.sender?.id;
|
|
@@ -267,9 +324,11 @@ class MainIPC {
|
|
|
267
324
|
_event.sender.send(`${openCurrentWebContentDevToolsChannel}-reply`, webContentId);
|
|
268
325
|
}
|
|
269
326
|
catch (error) {
|
|
270
|
-
|
|
327
|
+
log('error', 'openCurrentWebContentDevTools error:', error);
|
|
271
328
|
}
|
|
272
|
-
}
|
|
329
|
+
};
|
|
330
|
+
ipcMain.removeListener(openCurrentWebContentDevToolsChannel, openCurrentWebContentDevToolsHandler);
|
|
331
|
+
ipcMain.on(openCurrentWebContentDevToolsChannel, openCurrentWebContentDevToolsHandler);
|
|
273
332
|
}
|
|
274
333
|
}
|
|
275
334
|
/**
|
package/esm/main/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/main/index.ts"],"sourcesContent":["import { EventEmitter } from 'events'\nimport { ipcMain, webContents } from 'electron'\nimport { getRandomUUID } from '../common'\n\nexport let isInitialized = false;\n\n/**\n * 主进程 IPC 通信类\n * 负责处理主进程与渲染进程之间的消息通信\n * 使用单例模式确保全局唯一实例\n *\n * 修复说明:\n * - 为每个请求生成唯一的 requestId,解决并发请求数据错乱问题\n * - 确保请求和响应能够正确匹配,避免多个并发请求互相干扰\n */\nclass MainIPC {\n\tstatic instance: MainIPC\n\tprivate eventEmitter: EventEmitter = new EventEmitter()\n\n\tconstructor() {\n\t\tif (!MainIPC.instance) {\n\t\t\tthis.eventEmitter = new EventEmitter()\n\t\t\tMainIPC.instance = this\n\t\t}\n\t\treturn MainIPC.instance\n\t}\n\n /**\n * 发送给主进程消息\n * 使用唯一的 requestId 确保并发请求不会互相干扰\n *\n * @param channel 消息通道名称\n * @param args 传递给处理器的参数\n * @returns Promise<any> 返回处理结果\n *\n * 修复说明:\n * - 为每个请求生成唯一的 requestId\n * - 监听 `${channel}-reply-${requestId}` 事件,确保只接收对应请求的回复\n * - 发送请求时包含 requestId,让处理器知道如何回复\n */\n\tasync invokeMain(channel: string, ...args: any[]) {\n\t\treturn new Promise(resolve => {\n\t\t\tconst requestId = getRandomUUID()\n\t\t\tthis.eventEmitter.once(`${channel}-reply-${requestId}`, result => {\n\t\t\t\tresolve(result)\n\t\t\t})\n\t\t\tthis.eventEmitter.emit(channel, requestId, ...args)\n\t\t})\n\t}\n\n /**\n * 处理主进程发送过来的消息\n * 持续监听指定通道的消息\n *\n * @param channel 消息通道名称\n * @param handler 处理函数,接收除 requestId 外的所有参数\n *\n * 修复说明:\n * - 接收 requestId 作为第一个参数\n * - 使用 `${channel}-reply-${requestId}` 发送回复,确保回复给正确的请求\n * - 支持多个并发请求,每个请求都有独立的回复通道\n */\n\thandleMain(channel: string, handler: (...args: any[]) => Promise<any>) {\n\t\tthis.eventEmitter.on(channel, async (requestId: string, ...args) => {\n\t\t\tconst result = await handler(...args)\n\t\t\tthis.eventEmitter.emit(`${channel}-reply-${requestId}`, result)\n\t\t})\n return {\n cancel: () => {\n this.eventEmitter.removeAllListeners(channel)\n }\n };\n\t}\n\n /**\n * 发送给渲染进程消息\n * 使用唯一的 requestId 确保并发请求不会互相干扰\n *\n * @param webContents 目标渲染进程的 WebContents 对象\n * @param channel 消息通道名称\n * @param args 传递给渲染进程的参数\n * @returns Promise<any> 返回渲染进程的处理结果\n *\n * 修复说明:\n * - 为每个请求生成唯一的 requestId\n * - 监听 `${channel}-reply-${requestId}` 事件,确保只接收对应请求的回复\n * - 发送请求时包含 requestId,让渲染进程知道如何回复\n * - 等待渲染进程加载完成后再发送消息,确保消息能够被正确接收\n */\n\tinvokeRenderer(webContents: Electron.WebContents, channel: string, ...args: any[]): Promise<any> {\n\t\treturn new Promise(resolve => {\n\t\t\tconst requestId = getRandomUUID()\n\t\t\tconst sendMessage = () => {\n\t\t\t\tipcMain.once(`${channel}-reply-${requestId}`, (_event, result) => {\n\t\t\t\t\tresolve(result)\n\t\t\t\t})\n\t\t\t\twebContents.send(channel, requestId, ...args)\n\t\t\t}\n\n\t\t\t// 等待渲染进程加载完成后再推送,否则会导致渲染进程收不到消息\n\t\t\tif (webContents.isLoading()) {\n\t\t\t\twebContents.once('did-finish-load', () => {\n\t\t\t\t\tsetTimeout(() => sendMessage())\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tsendMessage()\n\t\t\t}\n\t\t})\n\t}\n\n /**\n * 发送给所有渲染进程消息\n * 向所有渲染进程发送消息并收集所有响应\n *\n * @param channel 消息通道名称\n * @param args 传递给所有渲染进程的参数\n * @returns Promise<any[]> 返回所有渲染进程的处理结果数组\n *\n * 修复说明:\n * - 为每个请求生成唯一的 requestId\n * - 收集所有渲染进程的响应,当所有响应都收到时才 resolve\n * - 使用 `${channel}-reply-${requestId}` 确保只接收对应请求的回复\n * - 如果没有渲染进程,直接返回空数组\n * - 等待每个渲染进程加载完成后再发送消息\n */\n\tinvokeAllRenderer(channel: string, ...args: any[]): Promise<any> {\n\t\treturn new Promise(resolve => {\n\t\t\tconst requestId = getRandomUUID()\n\t\t\tlet responseCount = 0\n\t\t\tconst totalWebContents = webContents.getAllWebContents().length\n\n\t\t\tif (totalWebContents === 0) {\n\t\t\t\tresolve([])\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst responses: any[] = []\n\n\t\t\twebContents.getAllWebContents().forEach(webContent => {\n\t\t\t\tconst sendMessage = () => {\n\t\t\t\t\tipcMain.once(`${channel}-reply-${requestId}`, (_event, result) => {\n\t\t\t\t\t\tresponses.push(result)\n\t\t\t\t\t\tresponseCount++\n\t\t\t\t\t\tif (responseCount === totalWebContents) {\n\t\t\t\t\t\t\tresolve(responses)\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t\twebContent.send(channel, requestId, ...args)\n\t\t\t\t}\n\n\t\t\t\t// 等待渲染进程加载完成后再推送,否则会导致渲染进程收不到消息\n\t\t\t\tif (webContent.isLoading()) {\n\t\t\t\t\twebContent.once('did-finish-load', () => {\n\t\t\t\t\t\tsetTimeout(() => sendMessage())\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tsendMessage()\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n\n /**\n * 处理渲染进程发送过来的消息\n * 持续监听指定通道的消息,支持超时处理\n *\n * @param channel 消息通道名称\n * @param handler 处理函数,接收除 requestId 外的所有参数\n *\n * 修复说明:\n * - 接收 requestId 作为第一个参数\n * - 使用 ipcMain.handle 替代 ipcMain.on,提供更好的错误处理\n * - 支持 8 秒超时机制,避免长时间等待\n * - 支持并发请求,每个请求都有独立的处理流程\n * - 提供详细的错误日志记录\n */\n\thandleRenderer(channel: string, handler: (...args: any[]) => Promise<any>) {\n try {\n ipcMain.handle(channel, async (event, ...args) => {\n try {\n const timeout = () => {\n return new Promise((_, reject) => {\n setTimeout(() => {\n reject(new Error('请求超时'));\n }, 1000 * 8); // 设定超时时间为8秒\n });\n }\n\n const processing = () => {\n return new Promise(async (_, reject) => {\n try {\n const data = await handler(...args);\n // console.error(`[${channel}] processing data: `, data, args);\n _(data);\n } catch (error) {\n reject(error);\n }\n });\n }\n // 这里是实际的异步操作\n const result = await Promise.race([processing(), timeout()]);\n // console.error(`[${channel}] handleRenderer result: `, result)\n return result; // 返回正常结果\n } catch (error) {\n console.error('SDK handleRenderer error: ', `channel: ${channel}`, error);\n // @ts-ignore\n return error?.message; // 返回超时错误信息\n }\n });\n } catch (error) {\n console.error('SDK handleRenderer error: ', error);\n }\n return {\n cancel: () => {\n ipcMain.removeHandler(channel)\n }\n };\n\t}\n /**\n * 初始化消息中继功能\n * 设置消息转发和回复机制,支持跨渲染进程通信\n *\n * 功能说明:\n * - relay-message: 转发消息到指定的渲染进程或所有渲染进程\n * - relay-reply: 处理回复消息,广播给所有渲染进程\n * - __GetCurrentWebContentId__: 获取当前 WebContent ID\n * - __OpenCurrentWebContentDevTools__: 打开当前 WebContent 的开发者工具\n */\n\trelayMessage() {\n\t\t// 处理消息转发请求\n\t\tipcMain.on('relay-message', (_event, { targetWebContentId, channel, requestId, args }) => {\n log('log', 'relay-message', { targetWebContentId, channel, requestId, args })\n\t\t\tif (targetWebContentId) {\n\t\t\t\t// 转发到指定的渲染进程\n\t\t\t\tconst targetWebContent = webContents.fromId(targetWebContentId)\n\t\t\t\tif (targetWebContent) {\n\t\t\t\t\ttargetWebContent.send(channel, requestId, ...args)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// 广播到所有渲染进程\n\t\t\t\twebContents.getAllWebContents().forEach(webContent => {\n\t\t\t\t\twebContent.send(channel, requestId, ...args)\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\n\t\t// 处理回复消息广播\n\t\tipcMain.on('relay-reply', (_event, { originalChannel, requestId, result }) => {\n log('log', 'relay-reply', { originalChannel, requestId, result })\n\t\t\t// 使用 requestId 确保回复发送给正确的请求\n\t\t\t// 所有渲染进程都会接收 ${originalChannel}-reply-${requestId} 事件\n\t\t\t// 只有对应的请求才会处理该回复,避免数据错乱\n webContents.getAllWebContents().forEach(webContent => {\n webContent.send(`${originalChannel}-reply-${requestId}`, result)\n })\n\t\t})\n\n // 获取当前 WebContent ID 的通道\n const getCurrentWebContentIdChannel = '__GetCurrentWebContentId__'\n ipcMain.on(getCurrentWebContentIdChannel, (_event) => {\n try {\n _event.frameId\n const webContentId = _event?.sender?.id;\n _event.sender.send(`${getCurrentWebContentIdChannel}-reply`, webContentId)\n } catch (error) {\n return undefined\n }\n\t\t})\n // 打开当前 WebContent 开发者工具的通道\n const openCurrentWebContentDevToolsChannel = '__OpenCurrentWebContentDevTools__'\n ipcMain.on(openCurrentWebContentDevToolsChannel, (_event) => {\n try {\n _event.frameId\n const webContentId = _event?.sender?.id;\n webContents.fromId(webContentId)?.openDevTools();\n _event.sender.send(`${openCurrentWebContentDevToolsChannel}-reply`, webContentId)\n } catch (error) {\n return undefined\n }\n\t\t})\n\n\t}\n\n}\n\n/**\n * 全局 MainIPC 实例\n * 使用全局变量确保单例模式,避免重复创建实例\n */\n// @ts-ignore\nexport const mainIPC: MainIPC = global['__ELECTRON_IPC__'] ? global['__ELECTRON_IPC__'] : (global['__ELECTRON_IPC__'] = new MainIPC());\n\n/**\n * 初始化 IPC 通信系统\n * 设置消息中继功能,确保跨进程通信正常工作\n *\n * @returns MainIPC 实例\n *\n * 功能说明:\n * - 检查是否已经初始化,避免重复初始化\n * - 设置消息中继功能,支持跨渲染进程通信\n * - 返回全局 MainIPC 实例\n */\nexport const initialize = () => {\n // @ts-ignore\n if (isInitialized && global['__ELECTRON_IPC__']){\n // @ts-ignore\n return global['__ELECTRON_IPC__']\n }\n isInitialized = true;\n // @ts-ignore\n global['__ELECTRON_IPC__'].relayMessage()\n // @ts-ignore\n return global['__ELECTRON_IPC__']\n}\n\n\n/**\n * 日志记录工具函数\n * 提供统一的日志格式和错误处理\n *\n * @param type 日志类型:'log' 或 'error'\n * @param data 要记录的数据\n */\nconst log = (type: 'log' | 'error', ...data: any[]) => {\n const key = `[electron-ipc]: `\n try {\n console[type](key, ...data);\n } catch (error) {\n console.error(key, error)\n }\n}\n\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/main/index.ts"],"sourcesContent":["import { EventEmitter } from 'events'\nimport { ipcMain, webContents } from 'electron'\nimport { getRandomUUID } from '../common'\n\nexport let isInitialized = false;\n\n/**\n * 主进程 IPC 通信类\n * 负责处理主进程与渲染进程之间的消息通信\n * 使用单例模式确保全局唯一实例\n *\n * 修复说明:\n * - 为每个请求生成唯一的 requestId,解决并发请求数据错乱问题\n * - 确保请求和响应能够正确匹配,避免多个并发请求互相干扰\n */\nclass MainIPC {\n\tstatic instance: MainIPC\n\tprivate eventEmitter: EventEmitter = new EventEmitter()\n\n\tconstructor() {\n\t\tif (!MainIPC.instance) {\n\t\t\tthis.eventEmitter = new EventEmitter()\n\t\t\tMainIPC.instance = this\n\t\t}\n\t\treturn MainIPC.instance\n\t}\n\n /**\n * 发送给主进程消息\n * 使用唯一的 requestId 确保并发请求不会互相干扰\n *\n * @param channel 消息通道名称\n * @param args 传递给处理器的参数\n * @returns Promise<any> 返回处理结果\n *\n * 修复说明:\n * - 为每个请求生成唯一的 requestId\n * - 监听 `${channel}-reply-${requestId}` 事件,确保只接收对应请求的回复\n * - 发送请求时包含 requestId,让处理器知道如何回复\n */\n\tasync invokeMain(channel: string, ...args: any[]): Promise<any> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst requestId = getRandomUUID()\n\t\t\tconst replyChannel = `${channel}-reply-${requestId}`\n\t\t\tlet isResolved = false\n\n\t\t\tconst replyHandler = (result: any) => {\n\t\t\t\tif (!isResolved) {\n\t\t\t\t\tisResolved = true\n\t\t\t\t\tthis.eventEmitter.removeListener(replyChannel, replyHandler)\n\t\t\t\t\tclearTimeout(timeoutId)\n\t\t\t\t\tresolve(result)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.eventEmitter.once(replyChannel, replyHandler)\n\n\t\t\t// 添加超时机制,确保监听器最终会被清理\n\t\t\tconst timeoutId = setTimeout(() => {\n\t\t\t\tif (!isResolved) {\n\t\t\t\t\tisResolved = true\n\t\t\t\t\tthis.eventEmitter.removeListener(replyChannel, replyHandler)\n\t\t\t\t\treject(new Error(`IPC request timeout: ${channel} (30s)`))\n\t\t\t\t}\n\t\t\t}, 30000) // 30秒超时\n\n\t\t\tthis.eventEmitter.emit(channel, requestId, ...args)\n\t\t})\n\t}\n\n /**\n * 处理主进程发送过来的消息\n * 持续监听指定通道的消息\n *\n * @param channel 消息通道名称\n * @param handler 处理函数,接收除 requestId 外的所有参数\n *\n * 修复说明:\n * - 接收 requestId 作为第一个参数\n * - 使用 `${channel}-reply-${requestId}` 发送回复,确保回复给正确的请求\n * - 支持多个并发请求,每个请求都有独立的回复通道\n */\n\thandleMain(channel: string, handler: (...args: any[]) => Promise<any>) {\n\t\tthis.eventEmitter.on(channel, async (requestId: string, ...args) => {\n\t\t\tconst result = await handler(...args)\n\t\t\tthis.eventEmitter.emit(`${channel}-reply-${requestId}`, result)\n\t\t})\n return {\n cancel: () => {\n this.eventEmitter.removeAllListeners(channel)\n }\n };\n\t}\n\n /**\n * 发送给渲染进程消息\n * 使用唯一的 requestId 确保并发请求不会互相干扰\n *\n * @param webContents 目标渲染进程的 WebContents 对象\n * @param channel 消息通道名称\n * @param args 传递给渲染进程的参数\n * @returns Promise<any> 返回渲染进程的处理结果\n *\n * 修复说明:\n * - 为每个请求生成唯一的 requestId\n * - 监听 `${channel}-reply-${requestId}` 事件,确保只接收对应请求的回复\n * - 发送请求时包含 requestId,让渲染进程知道如何回复\n * - 等待渲染进程加载完成后再发送消息,确保消息能够被正确接收\n */\n\tinvokeRenderer(webContents: Electron.WebContents, channel: string, ...args: any[]): Promise<any> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst requestId = getRandomUUID()\n\t\t\tconst replyChannel = `${channel}-reply-${requestId}`\n\t\t\tlet isResolved = false\n\n\t\t\tconst sendMessage = () => {\n\t\t\t\t// 检查 webContents 是否已销毁\n\t\t\t\tif (webContents.isDestroyed()) {\n\t\t\t\t\treject(new Error('WebContents has been destroyed'))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst replyHandler = (_event: Electron.IpcMainEvent, result: any) => {\n\t\t\t\t\tif (!isResolved) {\n\t\t\t\t\t\tisResolved = true\n\t\t\t\t\t\tipcMain.removeListener(replyChannel, replyHandler)\n\t\t\t\t\t\tclearTimeout(timeoutId)\n\t\t\t\t\t\tresolve(result)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tipcMain.once(replyChannel, replyHandler)\n\n\t\t\t\t// 添加超时机制,确保监听器最终会被清理\n\t\t\t\tconst timeoutId = setTimeout(() => {\n\t\t\t\t\tif (!isResolved) {\n\t\t\t\t\t\tisResolved = true\n\t\t\t\t\t\tipcMain.removeListener(replyChannel, replyHandler)\n\t\t\t\t\t\treject(new Error(`IPC request timeout: ${channel} (30s)`))\n\t\t\t\t\t}\n\t\t\t\t}, 30000) // 30秒超时\n\n\t\t\t\twebContents.send(channel, requestId, ...args)\n\t\t\t}\n\n\t\t\t// 等待渲染进程加载完成后再推送,否则会导致渲染进程收不到消息\n\t\t\tif (webContents.isLoading()) {\n\t\t\t\twebContents.once('did-finish-load', () => {\n\t\t\t\t\tsetTimeout(() => sendMessage())\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tsendMessage()\n\t\t\t}\n\t\t})\n\t}\n\n /**\n * 发送给所有渲染进程消息\n * 向所有渲染进程发送消息并收集所有响应\n *\n * @param channel 消息通道名称\n * @param args 传递给所有渲染进程的参数\n * @returns Promise<any[]> 返回所有渲染进程的处理结果数组\n *\n * 修复说明:\n * - 为每个请求生成唯一的 requestId\n * - 收集所有渲染进程的响应,当所有响应都收到时才 resolve\n * - 使用 `${channel}-reply-${requestId}` 确保只接收对应请求的回复\n * - 如果没有渲染进程,直接返回空数组\n * - 等待每个渲染进程加载完成后再发送消息\n */\n\tinvokeAllRenderer(channel: string, ...args: any[]): Promise<any> {\n\t\treturn new Promise(resolve => {\n\t\t\tconst requestId = getRandomUUID()\n\t\t\tlet responseCount = 0\n\t\t\tconst totalWebContents = webContents.getAllWebContents().length\n\n\t\t\tif (totalWebContents === 0) {\n\t\t\t\tresolve([])\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst responses: any[] = []\n\t\t\tconst replyChannel = `${channel}-reply-${requestId}`\n\n\t\t\t// 只注册一个监听器,避免内存泄漏\n\t\t\t// 使用 on 而不是 once,因为需要接收多个响应\n\t\t\tconst replyHandler = (_event: Electron.IpcMainEvent, result: any) => {\n\t\t\t\tresponses.push(result)\n\t\t\t\tresponseCount++\n\t\t\t\tif (responseCount === totalWebContents) {\n\t\t\t\t\t// 清理监听器\n\t\t\t\t\tipcMain.removeListener(replyChannel, replyHandler)\n\t\t\t\t\tclearTimeout(timeoutId)\n\t\t\t\t\tresolve(responses)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tipcMain.on(replyChannel, replyHandler)\n\n\t\t\t// 添加超时机制,确保监听器最终会被清理\n\t\t\tconst timeoutId = setTimeout(() => {\n\t\t\t\tipcMain.removeListener(replyChannel, replyHandler)\n\t\t\t\tif (responseCount < totalWebContents) {\n\t\t\t\t\t// 超时后返回已收到的响应\n\t\t\t\t\tresolve(responses)\n\t\t\t\t}\n\t\t\t}, 30000) // 30秒超时\n\n\t\t\twebContents.getAllWebContents().forEach(webContent => {\n\t\t\t\tconst sendMessage = () => {\n\t\t\t\t\twebContent.send(channel, requestId, ...args)\n\t\t\t\t}\n\n\t\t\t\t// 等待渲染进程加载完成后再推送,否则会导致渲染进程收不到消息\n\t\t\t\tif (webContent.isLoading()) {\n\t\t\t\t\twebContent.once('did-finish-load', () => {\n\t\t\t\t\t\tsetTimeout(() => sendMessage())\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tsendMessage()\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n\n /**\n * 处理渲染进程发送过来的消息\n * 持续监听指定通道的消息,支持超时处理\n *\n * @param channel 消息通道名称\n * @param handler 处理函数,接收除 requestId 外的所有参数\n *\n * 修复说明:\n * - 接收 requestId 作为第一个参数\n * - 使用 ipcMain.handle 替代 ipcMain.on,提供更好的错误处理\n * - 支持 8 秒超时机制,避免长时间等待\n * - 支持并发请求,每个请求都有独立的处理流程\n * - 提供详细的错误日志记录\n */\n\thandleRenderer(channel: string, handler: (...args: any[]) => Promise<any>) {\n try {\n ipcMain.handle(channel, async (event, ...args) => {\n try {\n const timeout = () => {\n return new Promise((resolve, reject) => {\n setTimeout(() => {\n reject(new Error('请求超时'));\n }, 1000 * 8); // 设定超时时间为8秒\n });\n }\n\n const processing = () => {\n return new Promise(async (resolve, reject) => {\n try {\n const data = await handler(...args);\n resolve(data);\n } catch (error) {\n reject(error);\n }\n });\n }\n // 这里是实际的异步操作\n const result = await Promise.race([processing(), timeout()]);\n // console.error(`[${channel}] handleRenderer result: `, result)\n return result; // 返回正常结果\n } catch (error) {\n log('error', 'SDK handleRenderer error: ', `channel: ${channel}`, error);\n // @ts-ignore\n return error?.message; // 返回超时错误信息\n }\n });\n } catch (error) {\n log('error', 'SDK handleRenderer error: ', error);\n }\n return {\n cancel: () => {\n ipcMain.removeHandler(channel)\n }\n };\n\t}\n /**\n * 初始化消息中继功能\n * 设置消息转发和回复机制,支持跨渲染进程通信\n *\n * 功能说明:\n * - relay-message: 转发消息到指定的渲染进程或所有渲染进程\n * - relay-reply: 处理回复消息,广播给所有渲染进程\n * - __GetCurrentWebContentId__: 获取当前 WebContent ID\n * - __OpenCurrentWebContentDevTools__: 打开当前 WebContent 的开发者工具\n */\n\trelayMessage() {\n\t\t// 防止重复注册监听器:先移除再添加\n\t\tconst relayMessageHandler = (_event: Electron.IpcMainEvent, { targetWebContentId, channel, requestId, args }: any) => {\n log('log', 'relay-message', { targetWebContentId, channel, requestId, args })\n\t\t\tif (targetWebContentId) {\n\t\t\t\t// 转发到指定的渲染进程\n\t\t\t\tconst targetWebContent = webContents.fromId(targetWebContentId)\n\t\t\t\tif (targetWebContent) {\n\t\t\t\t\ttargetWebContent.send(channel, requestId, ...args)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// 广播到所有渲染进程\n\t\t\t\twebContents.getAllWebContents().forEach(webContent => {\n\t\t\t\t\twebContent.send(channel, requestId, ...args)\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tipcMain.removeListener('relay-message', relayMessageHandler)\n\t\tipcMain.on('relay-message', relayMessageHandler)\n\n\t\t// 处理回复消息广播\n\t\tconst relayReplyHandler = (_event: Electron.IpcMainEvent, { originalChannel, requestId, result }: any) => {\n log('log', 'relay-reply', { originalChannel, requestId, result })\n\t\t\t// 使用 requestId 确保回复发送给正确的请求\n\t\t\t// 所有渲染进程都会接收 ${originalChannel}-reply-${requestId} 事件\n\t\t\t// 只有对应的请求才会处理该回复,避免数据错乱\n webContents.getAllWebContents().forEach(webContent => {\n webContent.send(`${originalChannel}-reply-${requestId}`, result)\n })\n\t\t}\n\n\t\tipcMain.removeListener('relay-reply', relayReplyHandler)\n\t\tipcMain.on('relay-reply', relayReplyHandler)\n\n // 获取当前 WebContent ID 的通道\n const getCurrentWebContentIdChannel = '__GetCurrentWebContentId__'\n const getCurrentWebContentIdHandler = (_event: Electron.IpcMainEvent) => {\n try {\n _event.frameId\n const webContentId = _event?.sender?.id;\n _event.sender.send(`${getCurrentWebContentIdChannel}-reply`, webContentId)\n } catch (error) {\n log('error', 'getCurrentWebContentId error:', error)\n }\n\t\t}\n\t\tipcMain.removeListener(getCurrentWebContentIdChannel, getCurrentWebContentIdHandler)\n ipcMain.on(getCurrentWebContentIdChannel, getCurrentWebContentIdHandler)\n\n // 打开当前 WebContent 开发者工具的通道\n const openCurrentWebContentDevToolsChannel = '__OpenCurrentWebContentDevTools__'\n const openCurrentWebContentDevToolsHandler = (_event: Electron.IpcMainEvent) => {\n try {\n _event.frameId\n const webContentId = _event?.sender?.id;\n webContents.fromId(webContentId)?.openDevTools();\n _event.sender.send(`${openCurrentWebContentDevToolsChannel}-reply`, webContentId)\n } catch (error) {\n log('error', 'openCurrentWebContentDevTools error:', error)\n }\n\t\t}\n\t\tipcMain.removeListener(openCurrentWebContentDevToolsChannel, openCurrentWebContentDevToolsHandler)\n ipcMain.on(openCurrentWebContentDevToolsChannel, openCurrentWebContentDevToolsHandler)\n\n\t}\n\n}\n\n/**\n * 全局 MainIPC 实例\n * 使用全局变量确保单例模式,避免重复创建实例\n */\n// @ts-ignore\nexport const mainIPC: MainIPC = global['__ELECTRON_IPC__'] ? global['__ELECTRON_IPC__'] : (global['__ELECTRON_IPC__'] = new MainIPC());\n\n/**\n * 初始化 IPC 通信系统\n * 设置消息中继功能,确保跨进程通信正常工作\n *\n * @returns MainIPC 实例\n *\n * 功能说明:\n * - 检查是否已经初始化,避免重复初始化\n * - 设置消息中继功能,支持跨渲染进程通信\n * - 返回全局 MainIPC 实例\n */\nexport const initialize = () => {\n // @ts-ignore\n if (isInitialized && global['__ELECTRON_IPC__']){\n // @ts-ignore\n return global['__ELECTRON_IPC__']\n }\n isInitialized = true;\n // @ts-ignore\n global['__ELECTRON_IPC__'].relayMessage()\n // @ts-ignore\n return global['__ELECTRON_IPC__']\n}\n\n\n/**\n * 日志记录工具函数\n * 提供统一的日志格式和错误处理\n *\n * @param type 日志类型:'log' 或 'error'\n * @param data 要记录的数据\n */\nconst log = (type: 'log' | 'error', ...data: any[]) => {\n const key = `[electron-ipc]: `\n try {\n console[type](key, ...data);\n } catch (error) {\n console.error(key, error)\n }\n}\n\n"],"names":[],"mappings":"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"}
|
package/main/index.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ declare class MainIPC {
|
|
|
25
25
|
* - 监听 `${channel}-reply-${requestId}` 事件,确保只接收对应请求的回复
|
|
26
26
|
* - 发送请求时包含 requestId,让处理器知道如何回复
|
|
27
27
|
*/
|
|
28
|
-
invokeMain(channel: string, ...args: any[]): Promise<
|
|
28
|
+
invokeMain(channel: string, ...args: any[]): Promise<any>;
|
|
29
29
|
/**
|
|
30
30
|
* 处理主进程发送过来的消息
|
|
31
31
|
* 持续监听指定通道的消息
|
package/main/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/main/index.ts"],"names":[],"mappings":"AAIA,eAAO,IAAI,aAAa,SAAQ,CAAC;AAEjC;;;;;;;;GAQG;AACH,cAAM,OAAO;IACZ,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAA;IACxB,OAAO,CAAC,YAAY,CAAmC;;IAUtD;;;;;;;;;;;;OAYG;IACE,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/main/index.ts"],"names":[],"mappings":"AAIA,eAAO,IAAI,aAAa,SAAQ,CAAC;AAEjC;;;;;;;;GAQG;AACH,cAAM,OAAO;IACZ,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAA;IACxB,OAAO,CAAC,YAAY,CAAmC;;IAUtD;;;;;;;;;;;;OAYG;IACE,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IA8B9D;;;;;;;;;;;OAWG;IACJ,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC;;;IAYpE;;;;;;;;;;;;;;OAcG;IACJ,cAAc,CAAC,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IA+C7F;;;;;;;;;;;;;;KAcC;IACJ,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IAuD/D;;;;;;;;;;;;;OAaG;IACJ,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC;;;IAyCxE;;;;;;;;;OASG;IACJ,YAAY;CAkEZ;AAED;;;GAGG;AAEH,eAAO,MAAM,OAAO,EAAE,OAAgH,CAAC;AAEvI;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,WAWtB,CAAA"}
|
package/main/index.js
CHANGED
|
@@ -35,11 +35,27 @@ class MainIPC {
|
|
|
35
35
|
* - 发送请求时包含 requestId,让处理器知道如何回复
|
|
36
36
|
*/
|
|
37
37
|
async invokeMain(channel, ...args) {
|
|
38
|
-
return new Promise(resolve => {
|
|
38
|
+
return new Promise((resolve, reject) => {
|
|
39
39
|
const requestId = index.getRandomUUID();
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
const replyChannel = `${channel}-reply-${requestId}`;
|
|
41
|
+
let isResolved = false;
|
|
42
|
+
const replyHandler = (result) => {
|
|
43
|
+
if (!isResolved) {
|
|
44
|
+
isResolved = true;
|
|
45
|
+
this.eventEmitter.removeListener(replyChannel, replyHandler);
|
|
46
|
+
clearTimeout(timeoutId);
|
|
47
|
+
resolve(result);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
this.eventEmitter.once(replyChannel, replyHandler);
|
|
51
|
+
// 添加超时机制,确保监听器最终会被清理
|
|
52
|
+
const timeoutId = setTimeout(() => {
|
|
53
|
+
if (!isResolved) {
|
|
54
|
+
isResolved = true;
|
|
55
|
+
this.eventEmitter.removeListener(replyChannel, replyHandler);
|
|
56
|
+
reject(new Error(`IPC request timeout: ${channel} (30s)`));
|
|
57
|
+
}
|
|
58
|
+
}, 30000); // 30秒超时
|
|
43
59
|
this.eventEmitter.emit(channel, requestId, ...args);
|
|
44
60
|
});
|
|
45
61
|
}
|
|
@@ -82,12 +98,33 @@ class MainIPC {
|
|
|
82
98
|
* - 等待渲染进程加载完成后再发送消息,确保消息能够被正确接收
|
|
83
99
|
*/
|
|
84
100
|
invokeRenderer(webContents, channel, ...args) {
|
|
85
|
-
return new Promise(resolve => {
|
|
101
|
+
return new Promise((resolve, reject) => {
|
|
86
102
|
const requestId = index.getRandomUUID();
|
|
103
|
+
const replyChannel = `${channel}-reply-${requestId}`;
|
|
104
|
+
let isResolved = false;
|
|
87
105
|
const sendMessage = () => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
106
|
+
// 检查 webContents 是否已销毁
|
|
107
|
+
if (webContents.isDestroyed()) {
|
|
108
|
+
reject(new Error('WebContents has been destroyed'));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const replyHandler = (_event, result) => {
|
|
112
|
+
if (!isResolved) {
|
|
113
|
+
isResolved = true;
|
|
114
|
+
electron.ipcMain.removeListener(replyChannel, replyHandler);
|
|
115
|
+
clearTimeout(timeoutId);
|
|
116
|
+
resolve(result);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
electron.ipcMain.once(replyChannel, replyHandler);
|
|
120
|
+
// 添加超时机制,确保监听器最终会被清理
|
|
121
|
+
const timeoutId = setTimeout(() => {
|
|
122
|
+
if (!isResolved) {
|
|
123
|
+
isResolved = true;
|
|
124
|
+
electron.ipcMain.removeListener(replyChannel, replyHandler);
|
|
125
|
+
reject(new Error(`IPC request timeout: ${channel} (30s)`));
|
|
126
|
+
}
|
|
127
|
+
}, 30000); // 30秒超时
|
|
91
128
|
webContents.send(channel, requestId, ...args);
|
|
92
129
|
};
|
|
93
130
|
// 等待渲染进程加载完成后再推送,否则会导致渲染进程收不到消息
|
|
@@ -126,15 +163,30 @@ class MainIPC {
|
|
|
126
163
|
return;
|
|
127
164
|
}
|
|
128
165
|
const responses = [];
|
|
166
|
+
const replyChannel = `${channel}-reply-${requestId}`;
|
|
167
|
+
// 只注册一个监听器,避免内存泄漏
|
|
168
|
+
// 使用 on 而不是 once,因为需要接收多个响应
|
|
169
|
+
const replyHandler = (_event, result) => {
|
|
170
|
+
responses.push(result);
|
|
171
|
+
responseCount++;
|
|
172
|
+
if (responseCount === totalWebContents) {
|
|
173
|
+
// 清理监听器
|
|
174
|
+
electron.ipcMain.removeListener(replyChannel, replyHandler);
|
|
175
|
+
clearTimeout(timeoutId);
|
|
176
|
+
resolve(responses);
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
electron.ipcMain.on(replyChannel, replyHandler);
|
|
180
|
+
// 添加超时机制,确保监听器最终会被清理
|
|
181
|
+
const timeoutId = setTimeout(() => {
|
|
182
|
+
electron.ipcMain.removeListener(replyChannel, replyHandler);
|
|
183
|
+
if (responseCount < totalWebContents) {
|
|
184
|
+
// 超时后返回已收到的响应
|
|
185
|
+
resolve(responses);
|
|
186
|
+
}
|
|
187
|
+
}, 30000); // 30秒超时
|
|
129
188
|
electron.webContents.getAllWebContents().forEach(webContent => {
|
|
130
189
|
const sendMessage = () => {
|
|
131
|
-
electron.ipcMain.once(`${channel}-reply-${requestId}`, (_event, result) => {
|
|
132
|
-
responses.push(result);
|
|
133
|
-
responseCount++;
|
|
134
|
-
if (responseCount === totalWebContents) {
|
|
135
|
-
resolve(responses);
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
190
|
webContent.send(channel, requestId, ...args);
|
|
139
191
|
};
|
|
140
192
|
// 等待渲染进程加载完成后再推送,否则会导致渲染进程收不到消息
|
|
@@ -168,18 +220,17 @@ class MainIPC {
|
|
|
168
220
|
electron.ipcMain.handle(channel, async (event, ...args) => {
|
|
169
221
|
try {
|
|
170
222
|
const timeout = () => {
|
|
171
|
-
return new Promise((
|
|
223
|
+
return new Promise((resolve, reject) => {
|
|
172
224
|
setTimeout(() => {
|
|
173
225
|
reject(new Error('请求超时'));
|
|
174
226
|
}, 1000 * 8); // 设定超时时间为8秒
|
|
175
227
|
});
|
|
176
228
|
};
|
|
177
229
|
const processing = () => {
|
|
178
|
-
return new Promise(async (
|
|
230
|
+
return new Promise(async (resolve, reject) => {
|
|
179
231
|
try {
|
|
180
232
|
const data = await handler(...args);
|
|
181
|
-
|
|
182
|
-
_(data);
|
|
233
|
+
resolve(data);
|
|
183
234
|
}
|
|
184
235
|
catch (error) {
|
|
185
236
|
reject(error);
|
|
@@ -192,14 +243,14 @@ class MainIPC {
|
|
|
192
243
|
return result; // 返回正常结果
|
|
193
244
|
}
|
|
194
245
|
catch (error) {
|
|
195
|
-
|
|
246
|
+
log('error', 'SDK handleRenderer error: ', `channel: ${channel}`, error);
|
|
196
247
|
// @ts-ignore
|
|
197
248
|
return error?.message; // 返回超时错误信息
|
|
198
249
|
}
|
|
199
250
|
});
|
|
200
251
|
}
|
|
201
252
|
catch (error) {
|
|
202
|
-
|
|
253
|
+
log('error', 'SDK handleRenderer error: ', error);
|
|
203
254
|
}
|
|
204
255
|
return {
|
|
205
256
|
cancel: () => {
|
|
@@ -218,8 +269,8 @@ class MainIPC {
|
|
|
218
269
|
* - __OpenCurrentWebContentDevTools__: 打开当前 WebContent 的开发者工具
|
|
219
270
|
*/
|
|
220
271
|
relayMessage() {
|
|
221
|
-
//
|
|
222
|
-
|
|
272
|
+
// 防止重复注册监听器:先移除再添加
|
|
273
|
+
const relayMessageHandler = (_event, { targetWebContentId, channel, requestId, args }) => {
|
|
223
274
|
log('log', 'relay-message', { targetWebContentId, channel, requestId, args });
|
|
224
275
|
if (targetWebContentId) {
|
|
225
276
|
// 转发到指定的渲染进程
|
|
@@ -234,9 +285,11 @@ class MainIPC {
|
|
|
234
285
|
webContent.send(channel, requestId, ...args);
|
|
235
286
|
});
|
|
236
287
|
}
|
|
237
|
-
}
|
|
288
|
+
};
|
|
289
|
+
electron.ipcMain.removeListener('relay-message', relayMessageHandler);
|
|
290
|
+
electron.ipcMain.on('relay-message', relayMessageHandler);
|
|
238
291
|
// 处理回复消息广播
|
|
239
|
-
|
|
292
|
+
const relayReplyHandler = (_event, { originalChannel, requestId, result }) => {
|
|
240
293
|
log('log', 'relay-reply', { originalChannel, requestId, result });
|
|
241
294
|
// 使用 requestId 确保回复发送给正确的请求
|
|
242
295
|
// 所有渲染进程都会接收 ${originalChannel}-reply-${requestId} 事件
|
|
@@ -244,22 +297,26 @@ class MainIPC {
|
|
|
244
297
|
electron.webContents.getAllWebContents().forEach(webContent => {
|
|
245
298
|
webContent.send(`${originalChannel}-reply-${requestId}`, result);
|
|
246
299
|
});
|
|
247
|
-
}
|
|
300
|
+
};
|
|
301
|
+
electron.ipcMain.removeListener('relay-reply', relayReplyHandler);
|
|
302
|
+
electron.ipcMain.on('relay-reply', relayReplyHandler);
|
|
248
303
|
// 获取当前 WebContent ID 的通道
|
|
249
304
|
const getCurrentWebContentIdChannel = '__GetCurrentWebContentId__';
|
|
250
|
-
|
|
305
|
+
const getCurrentWebContentIdHandler = (_event) => {
|
|
251
306
|
try {
|
|
252
307
|
_event.frameId;
|
|
253
308
|
const webContentId = _event?.sender?.id;
|
|
254
309
|
_event.sender.send(`${getCurrentWebContentIdChannel}-reply`, webContentId);
|
|
255
310
|
}
|
|
256
311
|
catch (error) {
|
|
257
|
-
|
|
312
|
+
log('error', 'getCurrentWebContentId error:', error);
|
|
258
313
|
}
|
|
259
|
-
}
|
|
314
|
+
};
|
|
315
|
+
electron.ipcMain.removeListener(getCurrentWebContentIdChannel, getCurrentWebContentIdHandler);
|
|
316
|
+
electron.ipcMain.on(getCurrentWebContentIdChannel, getCurrentWebContentIdHandler);
|
|
260
317
|
// 打开当前 WebContent 开发者工具的通道
|
|
261
318
|
const openCurrentWebContentDevToolsChannel = '__OpenCurrentWebContentDevTools__';
|
|
262
|
-
|
|
319
|
+
const openCurrentWebContentDevToolsHandler = (_event) => {
|
|
263
320
|
try {
|
|
264
321
|
_event.frameId;
|
|
265
322
|
const webContentId = _event?.sender?.id;
|
|
@@ -267,9 +324,11 @@ class MainIPC {
|
|
|
267
324
|
_event.sender.send(`${openCurrentWebContentDevToolsChannel}-reply`, webContentId);
|
|
268
325
|
}
|
|
269
326
|
catch (error) {
|
|
270
|
-
|
|
327
|
+
log('error', 'openCurrentWebContentDevTools error:', error);
|
|
271
328
|
}
|
|
272
|
-
}
|
|
329
|
+
};
|
|
330
|
+
electron.ipcMain.removeListener(openCurrentWebContentDevToolsChannel, openCurrentWebContentDevToolsHandler);
|
|
331
|
+
electron.ipcMain.on(openCurrentWebContentDevToolsChannel, openCurrentWebContentDevToolsHandler);
|
|
273
332
|
}
|
|
274
333
|
}
|
|
275
334
|
/**
|
package/main/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/src/main/index.ts"],"sourcesContent":["import { EventEmitter } from 'events'\nimport { ipcMain, webContents } from 'electron'\nimport { getRandomUUID } from '../common'\n\nexport let isInitialized = false;\n\n/**\n * 主进程 IPC 通信类\n * 负责处理主进程与渲染进程之间的消息通信\n * 使用单例模式确保全局唯一实例\n *\n * 修复说明:\n * - 为每个请求生成唯一的 requestId,解决并发请求数据错乱问题\n * - 确保请求和响应能够正确匹配,避免多个并发请求互相干扰\n */\nclass MainIPC {\n\tstatic instance: MainIPC\n\tprivate eventEmitter: EventEmitter = new EventEmitter()\n\n\tconstructor() {\n\t\tif (!MainIPC.instance) {\n\t\t\tthis.eventEmitter = new EventEmitter()\n\t\t\tMainIPC.instance = this\n\t\t}\n\t\treturn MainIPC.instance\n\t}\n\n /**\n * 发送给主进程消息\n * 使用唯一的 requestId 确保并发请求不会互相干扰\n *\n * @param channel 消息通道名称\n * @param args 传递给处理器的参数\n * @returns Promise<any> 返回处理结果\n *\n * 修复说明:\n * - 为每个请求生成唯一的 requestId\n * - 监听 `${channel}-reply-${requestId}` 事件,确保只接收对应请求的回复\n * - 发送请求时包含 requestId,让处理器知道如何回复\n */\n\tasync invokeMain(channel: string, ...args: any[]) {\n\t\treturn new Promise(resolve => {\n\t\t\tconst requestId = getRandomUUID()\n\t\t\tthis.eventEmitter.once(`${channel}-reply-${requestId}`, result => {\n\t\t\t\tresolve(result)\n\t\t\t})\n\t\t\tthis.eventEmitter.emit(channel, requestId, ...args)\n\t\t})\n\t}\n\n /**\n * 处理主进程发送过来的消息\n * 持续监听指定通道的消息\n *\n * @param channel 消息通道名称\n * @param handler 处理函数,接收除 requestId 外的所有参数\n *\n * 修复说明:\n * - 接收 requestId 作为第一个参数\n * - 使用 `${channel}-reply-${requestId}` 发送回复,确保回复给正确的请求\n * - 支持多个并发请求,每个请求都有独立的回复通道\n */\n\thandleMain(channel: string, handler: (...args: any[]) => Promise<any>) {\n\t\tthis.eventEmitter.on(channel, async (requestId: string, ...args) => {\n\t\t\tconst result = await handler(...args)\n\t\t\tthis.eventEmitter.emit(`${channel}-reply-${requestId}`, result)\n\t\t})\n return {\n cancel: () => {\n this.eventEmitter.removeAllListeners(channel)\n }\n };\n\t}\n\n /**\n * 发送给渲染进程消息\n * 使用唯一的 requestId 确保并发请求不会互相干扰\n *\n * @param webContents 目标渲染进程的 WebContents 对象\n * @param channel 消息通道名称\n * @param args 传递给渲染进程的参数\n * @returns Promise<any> 返回渲染进程的处理结果\n *\n * 修复说明:\n * - 为每个请求生成唯一的 requestId\n * - 监听 `${channel}-reply-${requestId}` 事件,确保只接收对应请求的回复\n * - 发送请求时包含 requestId,让渲染进程知道如何回复\n * - 等待渲染进程加载完成后再发送消息,确保消息能够被正确接收\n */\n\tinvokeRenderer(webContents: Electron.WebContents, channel: string, ...args: any[]): Promise<any> {\n\t\treturn new Promise(resolve => {\n\t\t\tconst requestId = getRandomUUID()\n\t\t\tconst sendMessage = () => {\n\t\t\t\tipcMain.once(`${channel}-reply-${requestId}`, (_event, result) => {\n\t\t\t\t\tresolve(result)\n\t\t\t\t})\n\t\t\t\twebContents.send(channel, requestId, ...args)\n\t\t\t}\n\n\t\t\t// 等待渲染进程加载完成后再推送,否则会导致渲染进程收不到消息\n\t\t\tif (webContents.isLoading()) {\n\t\t\t\twebContents.once('did-finish-load', () => {\n\t\t\t\t\tsetTimeout(() => sendMessage())\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tsendMessage()\n\t\t\t}\n\t\t})\n\t}\n\n /**\n * 发送给所有渲染进程消息\n * 向所有渲染进程发送消息并收集所有响应\n *\n * @param channel 消息通道名称\n * @param args 传递给所有渲染进程的参数\n * @returns Promise<any[]> 返回所有渲染进程的处理结果数组\n *\n * 修复说明:\n * - 为每个请求生成唯一的 requestId\n * - 收集所有渲染进程的响应,当所有响应都收到时才 resolve\n * - 使用 `${channel}-reply-${requestId}` 确保只接收对应请求的回复\n * - 如果没有渲染进程,直接返回空数组\n * - 等待每个渲染进程加载完成后再发送消息\n */\n\tinvokeAllRenderer(channel: string, ...args: any[]): Promise<any> {\n\t\treturn new Promise(resolve => {\n\t\t\tconst requestId = getRandomUUID()\n\t\t\tlet responseCount = 0\n\t\t\tconst totalWebContents = webContents.getAllWebContents().length\n\n\t\t\tif (totalWebContents === 0) {\n\t\t\t\tresolve([])\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst responses: any[] = []\n\n\t\t\twebContents.getAllWebContents().forEach(webContent => {\n\t\t\t\tconst sendMessage = () => {\n\t\t\t\t\tipcMain.once(`${channel}-reply-${requestId}`, (_event, result) => {\n\t\t\t\t\t\tresponses.push(result)\n\t\t\t\t\t\tresponseCount++\n\t\t\t\t\t\tif (responseCount === totalWebContents) {\n\t\t\t\t\t\t\tresolve(responses)\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t\twebContent.send(channel, requestId, ...args)\n\t\t\t\t}\n\n\t\t\t\t// 等待渲染进程加载完成后再推送,否则会导致渲染进程收不到消息\n\t\t\t\tif (webContent.isLoading()) {\n\t\t\t\t\twebContent.once('did-finish-load', () => {\n\t\t\t\t\t\tsetTimeout(() => sendMessage())\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tsendMessage()\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n\n /**\n * 处理渲染进程发送过来的消息\n * 持续监听指定通道的消息,支持超时处理\n *\n * @param channel 消息通道名称\n * @param handler 处理函数,接收除 requestId 外的所有参数\n *\n * 修复说明:\n * - 接收 requestId 作为第一个参数\n * - 使用 ipcMain.handle 替代 ipcMain.on,提供更好的错误处理\n * - 支持 8 秒超时机制,避免长时间等待\n * - 支持并发请求,每个请求都有独立的处理流程\n * - 提供详细的错误日志记录\n */\n\thandleRenderer(channel: string, handler: (...args: any[]) => Promise<any>) {\n try {\n ipcMain.handle(channel, async (event, ...args) => {\n try {\n const timeout = () => {\n return new Promise((_, reject) => {\n setTimeout(() => {\n reject(new Error('请求超时'));\n }, 1000 * 8); // 设定超时时间为8秒\n });\n }\n\n const processing = () => {\n return new Promise(async (_, reject) => {\n try {\n const data = await handler(...args);\n // console.error(`[${channel}] processing data: `, data, args);\n _(data);\n } catch (error) {\n reject(error);\n }\n });\n }\n // 这里是实际的异步操作\n const result = await Promise.race([processing(), timeout()]);\n // console.error(`[${channel}] handleRenderer result: `, result)\n return result; // 返回正常结果\n } catch (error) {\n console.error('SDK handleRenderer error: ', `channel: ${channel}`, error);\n // @ts-ignore\n return error?.message; // 返回超时错误信息\n }\n });\n } catch (error) {\n console.error('SDK handleRenderer error: ', error);\n }\n return {\n cancel: () => {\n ipcMain.removeHandler(channel)\n }\n };\n\t}\n /**\n * 初始化消息中继功能\n * 设置消息转发和回复机制,支持跨渲染进程通信\n *\n * 功能说明:\n * - relay-message: 转发消息到指定的渲染进程或所有渲染进程\n * - relay-reply: 处理回复消息,广播给所有渲染进程\n * - __GetCurrentWebContentId__: 获取当前 WebContent ID\n * - __OpenCurrentWebContentDevTools__: 打开当前 WebContent 的开发者工具\n */\n\trelayMessage() {\n\t\t// 处理消息转发请求\n\t\tipcMain.on('relay-message', (_event, { targetWebContentId, channel, requestId, args }) => {\n log('log', 'relay-message', { targetWebContentId, channel, requestId, args })\n\t\t\tif (targetWebContentId) {\n\t\t\t\t// 转发到指定的渲染进程\n\t\t\t\tconst targetWebContent = webContents.fromId(targetWebContentId)\n\t\t\t\tif (targetWebContent) {\n\t\t\t\t\ttargetWebContent.send(channel, requestId, ...args)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// 广播到所有渲染进程\n\t\t\t\twebContents.getAllWebContents().forEach(webContent => {\n\t\t\t\t\twebContent.send(channel, requestId, ...args)\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\n\t\t// 处理回复消息广播\n\t\tipcMain.on('relay-reply', (_event, { originalChannel, requestId, result }) => {\n log('log', 'relay-reply', { originalChannel, requestId, result })\n\t\t\t// 使用 requestId 确保回复发送给正确的请求\n\t\t\t// 所有渲染进程都会接收 ${originalChannel}-reply-${requestId} 事件\n\t\t\t// 只有对应的请求才会处理该回复,避免数据错乱\n webContents.getAllWebContents().forEach(webContent => {\n webContent.send(`${originalChannel}-reply-${requestId}`, result)\n })\n\t\t})\n\n // 获取当前 WebContent ID 的通道\n const getCurrentWebContentIdChannel = '__GetCurrentWebContentId__'\n ipcMain.on(getCurrentWebContentIdChannel, (_event) => {\n try {\n _event.frameId\n const webContentId = _event?.sender?.id;\n _event.sender.send(`${getCurrentWebContentIdChannel}-reply`, webContentId)\n } catch (error) {\n return undefined\n }\n\t\t})\n // 打开当前 WebContent 开发者工具的通道\n const openCurrentWebContentDevToolsChannel = '__OpenCurrentWebContentDevTools__'\n ipcMain.on(openCurrentWebContentDevToolsChannel, (_event) => {\n try {\n _event.frameId\n const webContentId = _event?.sender?.id;\n webContents.fromId(webContentId)?.openDevTools();\n _event.sender.send(`${openCurrentWebContentDevToolsChannel}-reply`, webContentId)\n } catch (error) {\n return undefined\n }\n\t\t})\n\n\t}\n\n}\n\n/**\n * 全局 MainIPC 实例\n * 使用全局变量确保单例模式,避免重复创建实例\n */\n// @ts-ignore\nexport const mainIPC: MainIPC = global['__ELECTRON_IPC__'] ? global['__ELECTRON_IPC__'] : (global['__ELECTRON_IPC__'] = new MainIPC());\n\n/**\n * 初始化 IPC 通信系统\n * 设置消息中继功能,确保跨进程通信正常工作\n *\n * @returns MainIPC 实例\n *\n * 功能说明:\n * - 检查是否已经初始化,避免重复初始化\n * - 设置消息中继功能,支持跨渲染进程通信\n * - 返回全局 MainIPC 实例\n */\nexport const initialize = () => {\n // @ts-ignore\n if (isInitialized && global['__ELECTRON_IPC__']){\n // @ts-ignore\n return global['__ELECTRON_IPC__']\n }\n isInitialized = true;\n // @ts-ignore\n global['__ELECTRON_IPC__'].relayMessage()\n // @ts-ignore\n return global['__ELECTRON_IPC__']\n}\n\n\n/**\n * 日志记录工具函数\n * 提供统一的日志格式和错误处理\n *\n * @param type 日志类型:'log' 或 'error'\n * @param data 要记录的数据\n */\nconst log = (type: 'log' | 'error', ...data: any[]) => {\n const key = `[electron-ipc]: `\n try {\n console[type](key, ...data);\n } catch (error) {\n console.error(key, error)\n }\n}\n\n"],"names":["isInitialized","EventEmitter","getRandomUUID","ipcMain","webContents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/src/main/index.ts"],"sourcesContent":["import { EventEmitter } from 'events'\nimport { ipcMain, webContents } from 'electron'\nimport { getRandomUUID } from '../common'\n\nexport let isInitialized = false;\n\n/**\n * 主进程 IPC 通信类\n * 负责处理主进程与渲染进程之间的消息通信\n * 使用单例模式确保全局唯一实例\n *\n * 修复说明:\n * - 为每个请求生成唯一的 requestId,解决并发请求数据错乱问题\n * - 确保请求和响应能够正确匹配,避免多个并发请求互相干扰\n */\nclass MainIPC {\n\tstatic instance: MainIPC\n\tprivate eventEmitter: EventEmitter = new EventEmitter()\n\n\tconstructor() {\n\t\tif (!MainIPC.instance) {\n\t\t\tthis.eventEmitter = new EventEmitter()\n\t\t\tMainIPC.instance = this\n\t\t}\n\t\treturn MainIPC.instance\n\t}\n\n /**\n * 发送给主进程消息\n * 使用唯一的 requestId 确保并发请求不会互相干扰\n *\n * @param channel 消息通道名称\n * @param args 传递给处理器的参数\n * @returns Promise<any> 返回处理结果\n *\n * 修复说明:\n * - 为每个请求生成唯一的 requestId\n * - 监听 `${channel}-reply-${requestId}` 事件,确保只接收对应请求的回复\n * - 发送请求时包含 requestId,让处理器知道如何回复\n */\n\tasync invokeMain(channel: string, ...args: any[]): Promise<any> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst requestId = getRandomUUID()\n\t\t\tconst replyChannel = `${channel}-reply-${requestId}`\n\t\t\tlet isResolved = false\n\n\t\t\tconst replyHandler = (result: any) => {\n\t\t\t\tif (!isResolved) {\n\t\t\t\t\tisResolved = true\n\t\t\t\t\tthis.eventEmitter.removeListener(replyChannel, replyHandler)\n\t\t\t\t\tclearTimeout(timeoutId)\n\t\t\t\t\tresolve(result)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.eventEmitter.once(replyChannel, replyHandler)\n\n\t\t\t// 添加超时机制,确保监听器最终会被清理\n\t\t\tconst timeoutId = setTimeout(() => {\n\t\t\t\tif (!isResolved) {\n\t\t\t\t\tisResolved = true\n\t\t\t\t\tthis.eventEmitter.removeListener(replyChannel, replyHandler)\n\t\t\t\t\treject(new Error(`IPC request timeout: ${channel} (30s)`))\n\t\t\t\t}\n\t\t\t}, 30000) // 30秒超时\n\n\t\t\tthis.eventEmitter.emit(channel, requestId, ...args)\n\t\t})\n\t}\n\n /**\n * 处理主进程发送过来的消息\n * 持续监听指定通道的消息\n *\n * @param channel 消息通道名称\n * @param handler 处理函数,接收除 requestId 外的所有参数\n *\n * 修复说明:\n * - 接收 requestId 作为第一个参数\n * - 使用 `${channel}-reply-${requestId}` 发送回复,确保回复给正确的请求\n * - 支持多个并发请求,每个请求都有独立的回复通道\n */\n\thandleMain(channel: string, handler: (...args: any[]) => Promise<any>) {\n\t\tthis.eventEmitter.on(channel, async (requestId: string, ...args) => {\n\t\t\tconst result = await handler(...args)\n\t\t\tthis.eventEmitter.emit(`${channel}-reply-${requestId}`, result)\n\t\t})\n return {\n cancel: () => {\n this.eventEmitter.removeAllListeners(channel)\n }\n };\n\t}\n\n /**\n * 发送给渲染进程消息\n * 使用唯一的 requestId 确保并发请求不会互相干扰\n *\n * @param webContents 目标渲染进程的 WebContents 对象\n * @param channel 消息通道名称\n * @param args 传递给渲染进程的参数\n * @returns Promise<any> 返回渲染进程的处理结果\n *\n * 修复说明:\n * - 为每个请求生成唯一的 requestId\n * - 监听 `${channel}-reply-${requestId}` 事件,确保只接收对应请求的回复\n * - 发送请求时包含 requestId,让渲染进程知道如何回复\n * - 等待渲染进程加载完成后再发送消息,确保消息能够被正确接收\n */\n\tinvokeRenderer(webContents: Electron.WebContents, channel: string, ...args: any[]): Promise<any> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst requestId = getRandomUUID()\n\t\t\tconst replyChannel = `${channel}-reply-${requestId}`\n\t\t\tlet isResolved = false\n\n\t\t\tconst sendMessage = () => {\n\t\t\t\t// 检查 webContents 是否已销毁\n\t\t\t\tif (webContents.isDestroyed()) {\n\t\t\t\t\treject(new Error('WebContents has been destroyed'))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst replyHandler = (_event: Electron.IpcMainEvent, result: any) => {\n\t\t\t\t\tif (!isResolved) {\n\t\t\t\t\t\tisResolved = true\n\t\t\t\t\t\tipcMain.removeListener(replyChannel, replyHandler)\n\t\t\t\t\t\tclearTimeout(timeoutId)\n\t\t\t\t\t\tresolve(result)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tipcMain.once(replyChannel, replyHandler)\n\n\t\t\t\t// 添加超时机制,确保监听器最终会被清理\n\t\t\t\tconst timeoutId = setTimeout(() => {\n\t\t\t\t\tif (!isResolved) {\n\t\t\t\t\t\tisResolved = true\n\t\t\t\t\t\tipcMain.removeListener(replyChannel, replyHandler)\n\t\t\t\t\t\treject(new Error(`IPC request timeout: ${channel} (30s)`))\n\t\t\t\t\t}\n\t\t\t\t}, 30000) // 30秒超时\n\n\t\t\t\twebContents.send(channel, requestId, ...args)\n\t\t\t}\n\n\t\t\t// 等待渲染进程加载完成后再推送,否则会导致渲染进程收不到消息\n\t\t\tif (webContents.isLoading()) {\n\t\t\t\twebContents.once('did-finish-load', () => {\n\t\t\t\t\tsetTimeout(() => sendMessage())\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tsendMessage()\n\t\t\t}\n\t\t})\n\t}\n\n /**\n * 发送给所有渲染进程消息\n * 向所有渲染进程发送消息并收集所有响应\n *\n * @param channel 消息通道名称\n * @param args 传递给所有渲染进程的参数\n * @returns Promise<any[]> 返回所有渲染进程的处理结果数组\n *\n * 修复说明:\n * - 为每个请求生成唯一的 requestId\n * - 收集所有渲染进程的响应,当所有响应都收到时才 resolve\n * - 使用 `${channel}-reply-${requestId}` 确保只接收对应请求的回复\n * - 如果没有渲染进程,直接返回空数组\n * - 等待每个渲染进程加载完成后再发送消息\n */\n\tinvokeAllRenderer(channel: string, ...args: any[]): Promise<any> {\n\t\treturn new Promise(resolve => {\n\t\t\tconst requestId = getRandomUUID()\n\t\t\tlet responseCount = 0\n\t\t\tconst totalWebContents = webContents.getAllWebContents().length\n\n\t\t\tif (totalWebContents === 0) {\n\t\t\t\tresolve([])\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst responses: any[] = []\n\t\t\tconst replyChannel = `${channel}-reply-${requestId}`\n\n\t\t\t// 只注册一个监听器,避免内存泄漏\n\t\t\t// 使用 on 而不是 once,因为需要接收多个响应\n\t\t\tconst replyHandler = (_event: Electron.IpcMainEvent, result: any) => {\n\t\t\t\tresponses.push(result)\n\t\t\t\tresponseCount++\n\t\t\t\tif (responseCount === totalWebContents) {\n\t\t\t\t\t// 清理监听器\n\t\t\t\t\tipcMain.removeListener(replyChannel, replyHandler)\n\t\t\t\t\tclearTimeout(timeoutId)\n\t\t\t\t\tresolve(responses)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tipcMain.on(replyChannel, replyHandler)\n\n\t\t\t// 添加超时机制,确保监听器最终会被清理\n\t\t\tconst timeoutId = setTimeout(() => {\n\t\t\t\tipcMain.removeListener(replyChannel, replyHandler)\n\t\t\t\tif (responseCount < totalWebContents) {\n\t\t\t\t\t// 超时后返回已收到的响应\n\t\t\t\t\tresolve(responses)\n\t\t\t\t}\n\t\t\t}, 30000) // 30秒超时\n\n\t\t\twebContents.getAllWebContents().forEach(webContent => {\n\t\t\t\tconst sendMessage = () => {\n\t\t\t\t\twebContent.send(channel, requestId, ...args)\n\t\t\t\t}\n\n\t\t\t\t// 等待渲染进程加载完成后再推送,否则会导致渲染进程收不到消息\n\t\t\t\tif (webContent.isLoading()) {\n\t\t\t\t\twebContent.once('did-finish-load', () => {\n\t\t\t\t\t\tsetTimeout(() => sendMessage())\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tsendMessage()\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n\n /**\n * 处理渲染进程发送过来的消息\n * 持续监听指定通道的消息,支持超时处理\n *\n * @param channel 消息通道名称\n * @param handler 处理函数,接收除 requestId 外的所有参数\n *\n * 修复说明:\n * - 接收 requestId 作为第一个参数\n * - 使用 ipcMain.handle 替代 ipcMain.on,提供更好的错误处理\n * - 支持 8 秒超时机制,避免长时间等待\n * - 支持并发请求,每个请求都有独立的处理流程\n * - 提供详细的错误日志记录\n */\n\thandleRenderer(channel: string, handler: (...args: any[]) => Promise<any>) {\n try {\n ipcMain.handle(channel, async (event, ...args) => {\n try {\n const timeout = () => {\n return new Promise((resolve, reject) => {\n setTimeout(() => {\n reject(new Error('请求超时'));\n }, 1000 * 8); // 设定超时时间为8秒\n });\n }\n\n const processing = () => {\n return new Promise(async (resolve, reject) => {\n try {\n const data = await handler(...args);\n resolve(data);\n } catch (error) {\n reject(error);\n }\n });\n }\n // 这里是实际的异步操作\n const result = await Promise.race([processing(), timeout()]);\n // console.error(`[${channel}] handleRenderer result: `, result)\n return result; // 返回正常结果\n } catch (error) {\n log('error', 'SDK handleRenderer error: ', `channel: ${channel}`, error);\n // @ts-ignore\n return error?.message; // 返回超时错误信息\n }\n });\n } catch (error) {\n log('error', 'SDK handleRenderer error: ', error);\n }\n return {\n cancel: () => {\n ipcMain.removeHandler(channel)\n }\n };\n\t}\n /**\n * 初始化消息中继功能\n * 设置消息转发和回复机制,支持跨渲染进程通信\n *\n * 功能说明:\n * - relay-message: 转发消息到指定的渲染进程或所有渲染进程\n * - relay-reply: 处理回复消息,广播给所有渲染进程\n * - __GetCurrentWebContentId__: 获取当前 WebContent ID\n * - __OpenCurrentWebContentDevTools__: 打开当前 WebContent 的开发者工具\n */\n\trelayMessage() {\n\t\t// 防止重复注册监听器:先移除再添加\n\t\tconst relayMessageHandler = (_event: Electron.IpcMainEvent, { targetWebContentId, channel, requestId, args }: any) => {\n log('log', 'relay-message', { targetWebContentId, channel, requestId, args })\n\t\t\tif (targetWebContentId) {\n\t\t\t\t// 转发到指定的渲染进程\n\t\t\t\tconst targetWebContent = webContents.fromId(targetWebContentId)\n\t\t\t\tif (targetWebContent) {\n\t\t\t\t\ttargetWebContent.send(channel, requestId, ...args)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// 广播到所有渲染进程\n\t\t\t\twebContents.getAllWebContents().forEach(webContent => {\n\t\t\t\t\twebContent.send(channel, requestId, ...args)\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tipcMain.removeListener('relay-message', relayMessageHandler)\n\t\tipcMain.on('relay-message', relayMessageHandler)\n\n\t\t// 处理回复消息广播\n\t\tconst relayReplyHandler = (_event: Electron.IpcMainEvent, { originalChannel, requestId, result }: any) => {\n log('log', 'relay-reply', { originalChannel, requestId, result })\n\t\t\t// 使用 requestId 确保回复发送给正确的请求\n\t\t\t// 所有渲染进程都会接收 ${originalChannel}-reply-${requestId} 事件\n\t\t\t// 只有对应的请求才会处理该回复,避免数据错乱\n webContents.getAllWebContents().forEach(webContent => {\n webContent.send(`${originalChannel}-reply-${requestId}`, result)\n })\n\t\t}\n\n\t\tipcMain.removeListener('relay-reply', relayReplyHandler)\n\t\tipcMain.on('relay-reply', relayReplyHandler)\n\n // 获取当前 WebContent ID 的通道\n const getCurrentWebContentIdChannel = '__GetCurrentWebContentId__'\n const getCurrentWebContentIdHandler = (_event: Electron.IpcMainEvent) => {\n try {\n _event.frameId\n const webContentId = _event?.sender?.id;\n _event.sender.send(`${getCurrentWebContentIdChannel}-reply`, webContentId)\n } catch (error) {\n log('error', 'getCurrentWebContentId error:', error)\n }\n\t\t}\n\t\tipcMain.removeListener(getCurrentWebContentIdChannel, getCurrentWebContentIdHandler)\n ipcMain.on(getCurrentWebContentIdChannel, getCurrentWebContentIdHandler)\n\n // 打开当前 WebContent 开发者工具的通道\n const openCurrentWebContentDevToolsChannel = '__OpenCurrentWebContentDevTools__'\n const openCurrentWebContentDevToolsHandler = (_event: Electron.IpcMainEvent) => {\n try {\n _event.frameId\n const webContentId = _event?.sender?.id;\n webContents.fromId(webContentId)?.openDevTools();\n _event.sender.send(`${openCurrentWebContentDevToolsChannel}-reply`, webContentId)\n } catch (error) {\n log('error', 'openCurrentWebContentDevTools error:', error)\n }\n\t\t}\n\t\tipcMain.removeListener(openCurrentWebContentDevToolsChannel, openCurrentWebContentDevToolsHandler)\n ipcMain.on(openCurrentWebContentDevToolsChannel, openCurrentWebContentDevToolsHandler)\n\n\t}\n\n}\n\n/**\n * 全局 MainIPC 实例\n * 使用全局变量确保单例模式,避免重复创建实例\n */\n// @ts-ignore\nexport const mainIPC: MainIPC = global['__ELECTRON_IPC__'] ? global['__ELECTRON_IPC__'] : (global['__ELECTRON_IPC__'] = new MainIPC());\n\n/**\n * 初始化 IPC 通信系统\n * 设置消息中继功能,确保跨进程通信正常工作\n *\n * @returns MainIPC 实例\n *\n * 功能说明:\n * - 检查是否已经初始化,避免重复初始化\n * - 设置消息中继功能,支持跨渲染进程通信\n * - 返回全局 MainIPC 实例\n */\nexport const initialize = () => {\n // @ts-ignore\n if (isInitialized && global['__ELECTRON_IPC__']){\n // @ts-ignore\n return global['__ELECTRON_IPC__']\n }\n isInitialized = true;\n // @ts-ignore\n global['__ELECTRON_IPC__'].relayMessage()\n // @ts-ignore\n return global['__ELECTRON_IPC__']\n}\n\n\n/**\n * 日志记录工具函数\n * 提供统一的日志格式和错误处理\n *\n * @param type 日志类型:'log' 或 'error'\n * @param data 要记录的数据\n */\nconst log = (type: 'log' | 'error', ...data: any[]) => {\n const key = `[electron-ipc]: `\n try {\n console[type](key, ...data);\n } catch (error) {\n console.error(key, error)\n }\n}\n\n"],"names":["isInitialized","EventEmitter","getRandomUUID","ipcMain","webContents"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lynker-desktop/electron-ipc",
|
|
3
|
-
"version": "0.0.9-alpha.
|
|
3
|
+
"version": "0.0.9-alpha.50",
|
|
4
4
|
"description": "electron-ipc",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"electron",
|
|
@@ -73,5 +73,5 @@
|
|
|
73
73
|
"tslib": "^2.6.3",
|
|
74
74
|
"typescript": "^5.5.3"
|
|
75
75
|
},
|
|
76
|
-
"gitHead": "
|
|
76
|
+
"gitHead": "14f11a25036085111e94ba989cbec279ae47b985"
|
|
77
77
|
}
|