contextBridge.exposeInMainWorld 在 preload.ts 中:ipcRenderer 从 main.ts 接收到消息,但渲染器没有得到它
contextBridge.exposeInMainWorld in preload.ts: ipcRenderer receives the message from main.ts but the renderer doesn't get it
在 Electron-React-Typescript 应用程序中,我设法在预加载时通过 contextBridge.exposeInMainWorld 将消息从渲染器进程发送到主进程,但在返回的路上,从主进程处理的输出实际上通过并到达preload.ts,但未到达渲染器进程。
这一定是真的“愚蠢”的东西,但我不知道“罪魁祸首”是什么。所以,我请求你的帮助。
preload.ts :
const {
contextBridge,
ipcRenderer
} = require("electron")
contextBridge.exposeInMainWorld(
"api", {
send: (channel, data) => {
ipcRenderer.invoke(channel, data).catch(e => console.log(e))
},
receive: (channel, func) => {
ipcRenderer.on(channel, (event, ...args) => func(...args))
//ipcRenderer.on(channel, (event, ...args) => {
//console.log("ipcRenderer.on-args: ", args);
//});
}
)
index.d.ts :
declare interface Window {
api: {
send: (channel: string, ...arg: any) => void;
receive: (channel: string, func: (event: any, ...arg: any) => void) => void;
}
}
main.ts :
ipcMain.handle("path-to-url", (IpcMainEvent, path) => {
console.log("received a request from viewerDemo");
if (mainWindow) {
let urlified = url.pathToFileURL(path);
console.log("urlified = url.pathToFileURL(path) : ", urlified);
console.log("urlified.href= ", urlified.href);
console.log("urlified.pathname= ", url.pathToFileURL(path).pathname);
mainWindow.webContents.on("dom-ready", () => {
mainWindow.webContents.send("path-to-url", "ohhhhhhhhhhhhhhhh");
mainWindow.webContents.send("path-to-url", url.pathToFileURL(path).pathname);
});
}
});
渲染器进程(数据未正确显示!):
viewerDemo.tsx
import * as React from 'react';
import Viewer from 'react-viewer';
let path_1 = './images/natural-scene.jpeg';
let url_path;
const pathToUrlFunc = (path): string => {
console.log("pathToUrlFunc called");
window.api.send("path-to-url", path);
let urlPath;
window.api.receive("path-to-url", (event, args) => {
console.log("window.api.receive called!");
console.log("window.api.receive-args[0]: ", args[0]);
urlPath = args[0];
});
return urlPath;
}
function ViewerDemo() {
const [ visible, setVisible ] = React.useState(false);
let urlpath = pathToUrlFunc(path_1);
console.log("urlpath: ", urlpath);
return (
<div>
<button onClick={() => { setVisible(true); } }>show</button>
<Viewer
visible={visible}
onClose={() => { setVisible(false); } }
images={[{src: 'https://www.fotolip.com/wp-content/uploads/2016/05/Nature-Scenes-
21.jpg', alt: ''}]}
//images={[{src: urlpath, alt: ''}]}
/>
</div>
);
}
export default ViewerDemo;
主要我得到:path received from main: ./images/natural-scene.jpeg
而从主渲染器返回的路上我得到:Cannot read property '0' of undefined
如果在 contextBridge.exposeInMainWorld 中 api 的 'receive' 部分,我输入:
receive: (channel, func) => {
//ipcRenderer.on(channel, (event, ...args) => func(...args))
ipcRenderer.on(channel, (event, ...args) => {
console.log("ipcRenderer.on-args: ", args);
});
}
我不再收到该错误,在 preload.ts 内出现了来自 main.ts 的正确消息,但渲染器进程仍然没有收到它:
你现在可能已经找到了这个问题的答案,但为了以防万一,为了任何遇到这个问题的人的利益;虽然我无法 运行 代码来证明这是问题所在,但我认为它是预加载接收函数的问题:
ipcRenderer.on 代理方法仅使用 args 参数的传播来调用您的“func”处理程序。但是在 viewerDemo.tsx 中,您传递给“receive”的处理程序方法被称为“func”,需要两个参数“event”和“args”。因此,您在 args 中传递的单个参数可能在“事件”参数中显示为单个元素数组。
为了检验理论并希望解决这个问题,请使方法保持一致。您可以将 viewerDemo.tsx 中的处理程序中的这一行从
更改为
window.api.receive("path-to-url", (event, args) => {
至
window.api.receive("path-to-url", (args) => {
或在 preload.ts 中更改此行
ipcRenderer.on(channel, (event, ...args) => func(...args))
至
ipcRenderer.on(channel, (event, ...args) => func(event, ...args))
应该可以解决问题。
在 Electron-React-Typescript 应用程序中,我设法在预加载时通过 contextBridge.exposeInMainWorld 将消息从渲染器进程发送到主进程,但在返回的路上,从主进程处理的输出实际上通过并到达preload.ts,但未到达渲染器进程。 这一定是真的“愚蠢”的东西,但我不知道“罪魁祸首”是什么。所以,我请求你的帮助。
preload.ts :
const {
contextBridge,
ipcRenderer
} = require("electron")
contextBridge.exposeInMainWorld(
"api", {
send: (channel, data) => {
ipcRenderer.invoke(channel, data).catch(e => console.log(e))
},
receive: (channel, func) => {
ipcRenderer.on(channel, (event, ...args) => func(...args))
//ipcRenderer.on(channel, (event, ...args) => {
//console.log("ipcRenderer.on-args: ", args);
//});
}
)
index.d.ts :
declare interface Window {
api: {
send: (channel: string, ...arg: any) => void;
receive: (channel: string, func: (event: any, ...arg: any) => void) => void;
}
}
main.ts :
ipcMain.handle("path-to-url", (IpcMainEvent, path) => {
console.log("received a request from viewerDemo");
if (mainWindow) {
let urlified = url.pathToFileURL(path);
console.log("urlified = url.pathToFileURL(path) : ", urlified);
console.log("urlified.href= ", urlified.href);
console.log("urlified.pathname= ", url.pathToFileURL(path).pathname);
mainWindow.webContents.on("dom-ready", () => {
mainWindow.webContents.send("path-to-url", "ohhhhhhhhhhhhhhhh");
mainWindow.webContents.send("path-to-url", url.pathToFileURL(path).pathname);
});
}
});
渲染器进程(数据未正确显示!):
viewerDemo.tsx
import * as React from 'react';
import Viewer from 'react-viewer';
let path_1 = './images/natural-scene.jpeg';
let url_path;
const pathToUrlFunc = (path): string => {
console.log("pathToUrlFunc called");
window.api.send("path-to-url", path);
let urlPath;
window.api.receive("path-to-url", (event, args) => {
console.log("window.api.receive called!");
console.log("window.api.receive-args[0]: ", args[0]);
urlPath = args[0];
});
return urlPath;
}
function ViewerDemo() {
const [ visible, setVisible ] = React.useState(false);
let urlpath = pathToUrlFunc(path_1);
console.log("urlpath: ", urlpath);
return (
<div>
<button onClick={() => { setVisible(true); } }>show</button>
<Viewer
visible={visible}
onClose={() => { setVisible(false); } }
images={[{src: 'https://www.fotolip.com/wp-content/uploads/2016/05/Nature-Scenes-
21.jpg', alt: ''}]}
//images={[{src: urlpath, alt: ''}]}
/>
</div>
);
}
export default ViewerDemo;
主要我得到:path received from main: ./images/natural-scene.jpeg
而从主渲染器返回的路上我得到:Cannot read property '0' of undefined
如果在 contextBridge.exposeInMainWorld 中 api 的 'receive' 部分,我输入:
receive: (channel, func) => {
//ipcRenderer.on(channel, (event, ...args) => func(...args))
ipcRenderer.on(channel, (event, ...args) => {
console.log("ipcRenderer.on-args: ", args);
});
}
我不再收到该错误,在 preload.ts 内出现了来自 main.ts 的正确消息,但渲染器进程仍然没有收到它:
你现在可能已经找到了这个问题的答案,但为了以防万一,为了任何遇到这个问题的人的利益;虽然我无法 运行 代码来证明这是问题所在,但我认为它是预加载接收函数的问题:
ipcRenderer.on 代理方法仅使用 args 参数的传播来调用您的“func”处理程序。但是在 viewerDemo.tsx 中,您传递给“receive”的处理程序方法被称为“func”,需要两个参数“event”和“args”。因此,您在 args 中传递的单个参数可能在“事件”参数中显示为单个元素数组。
为了检验理论并希望解决这个问题,请使方法保持一致。您可以将 viewerDemo.tsx 中的处理程序中的这一行从
更改为window.api.receive("path-to-url", (event, args) => {
至
window.api.receive("path-to-url", (args) => {
或在 preload.ts 中更改此行
ipcRenderer.on(channel, (event, ...args) => func(...args))
至
ipcRenderer.on(channel, (event, ...args) => func(event, ...args))
应该可以解决问题。