我有一个Electron应用程序,它有多个按钮可以生成文档。这些文档实际上只是HTML页面,它们被加载到一个新的BrowserWindow中,并通过IPC接收自定义参数,然后通过JavaScript注入文档。
对于通过IPC传递参数,我使用了一个我称为'document-params'
的通道。所有文档都使用这个通道。我的期望是发送到通道的消息将被其侦听器消耗,并从Electron正在使用的任何IPC队列中消失。相反,就好像发送到该通道的所有消息都保留在通道中一样。每个新的文档调用都会接收通道中所有以前的消息,沿着。如果我多次调用同一个文档,它的数据会多次插入到文档中。如果我调用不同的文档,我可以看到前一个文档的注入函数无法在当前文档下运行(调用document.getElementById()
)失败。
据我所知,我遵循Electron IPC教程。我在文档中没有看到任何地方提到消息保留在IPC通道中,这无论如何都是违反直觉的行为。
下面是我的代码是如何设置的:
我有两个文档,每个文档在package.json中定义为自己的入口点:
{
"name": "document_contract",
"html": "./src/renderer/windows/documents/Contract.html",
"js": "./src/renderer/windows/documents/renderer.js",
"preload": {
"js": "./src/renderer/windows/documents/preload.js"
}
},
{
"name": "document_review_draft",
"html": "./src/renderer/windows/documents/ReviewDraft.html",
"js": "./src/renderer/windows/documents/renderer.js",
"preload": {
"js": "./src/renderer/windows/documents/preload.js"
}
}
字符串
下面是renderer.js和preload.js文件
/src/renderer/windows/documents/preload.js:
const { contextBridge } = require('electron');
import { preloadCommon } from '../preload.js';
contextBridge.exposeInMainWorld('electronAPI', {...preloadCommon});
型
../preload.js:
const { ipcRenderer } = require('electron');
export const preloadCommon = {
subscribe: (channel, callback) => {
ipcRenderer.on(channel, callback);
},
getPopupParams: () => {
ipcRenderer.send('popup-params');
},
getDocumentParams: () => {
ipcRenderer.send('document-params');
},
popup: (name, data) => {
ipcRenderer.send('popup', name, data);
},
generateDocument: (template, title, data) => {
ipcRenderer.send('document', template, title, data);
}
};
型
/src/renderer/windows/documents/renderer.js:
import '../renderer.js';
function bootstrapContract(data) {
// Document appropriate DOM manipulation, such as injecting <li> elements from data
}
function bootstrapReviewDraft(data) {
// Document appropriate DOM manipulation, such as injecting <li> elements from data
}
function dispatch(template, data) {
switch (template) {
case 'contract':
bootstrapContract(data);
break;
case 'review-draft':
bootstrapReviewDraft(data);
break;
default:
break;
}
}
window.electronAPI.subscribe('document-params', (event, template, data) => dispatch(template, data));
window.electronAPI.getDocumentParams();
型
在主进程中,以下是如何处理通道的:
const { ipcMain, BrowserWindow } = require("electron");
const path = require('path');
let popup;
const templates = {
'contract': DOCUMENT_CONTRACT_WEBPACK_ENTRY,
'review-draft': DOCUMENT_REVIEW_DRAFT_WEBPACK_ENTRY,
};
const createDocument = (template, title, data) => {
popup = new BrowserWindow({
show: true,
webPreferences: {
preload: DOCUMENT_CONTRACT_PRELOAD_WEBPACK_ENTRY
},
title: title,
parent: global.mainWindow,
modal: true,
});
popup.loadURL(templates[template]);
popup.maximize();
popup.show();
};
ipcMain.on('document', (event, template, title, data) => {
const onPassParamsToDocument = (event) => {
event.sender.send('document-params', template, data);
};
ipcMain.on('document-params', onPassParamsToDocument);
createDocument(template, title, data);
});
型
1条答案
按热度按时间0yg35tkg1#
在main上,每次在
"document"
通道上收到消息时,都会为"document-params"
创建一个新的侦听器。由于从未删除这些侦听器,因此可以肯定这会导致问题。IPC侦听器可以使用
ipcMain.removeListener()
或ipcMain.removeAllListeners()
删除。你的实现似乎也过于复杂,当你调用main并期望响应时,你可能应该考虑使用
invoke
/handle
而不是send
/on
。