如何使用 preload.js 将 ipcRenderer.invoke 处理程序答案传递给电子渲染器进程

问题描述 投票:0回答:1

我正在编写一个 CRA + Electron 应用程序,我需要使用 ipcRenderer.invoke 进行进程间通信。我能够使 ipcRenderer.send 和 ipcRender.on 在 contextIsolation 模式下工作,但 ipcRender.invoke 却没有成功。由于某种我不明白的原因,我无法以任何形式(承诺或值)将处理程序响应返回给渲染器,我得到的只是“未定义”值。

预加载.js

const { contextBridge, ipcRenderer } = require('electron');

 // whitelist channels
const validChannels = ["toMain", "fromMain", "invokeMain"]
// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld(
    "apiKey", {
        sendApi: (channel, ...args) => {
            if (validChannels.includes(channel)) {
                ipcRenderer.send(channel, ...args);
            }
        },
        onApi: (channel, func) => {
            if (validChannels.includes(channel)) {
                // Deliberately strip event in func as it includes `sender` 
                ipcRenderer.on(channel, (event, ...args) => func(...args));
            }
        },
        invokeApi: (channel, ...args) => {
            if ( validChannels.includes(channel) ) {
                ipcRenderer.invoke(channel, ...args).then( (value) =>{
                    console.log('apiKey.invokeApi:', value);
                    return value;
                });
            };
        },
    }
);

main.js

ipcMain.handle('invokeMain', async (event, ...arg) => {
  console.log ('invokeMain received arg:', ...arg);
  let response = 'pong';  
  //return new Promise( (resolve) => setTimeout(resolve(response), 2000), (reject) => reject() );
  let prom = new Promise( (resolve) => setTimeout(resolve(response), 2000), (reject) => reject() );
  let result = await prom;
  console.log ('invokeMain response to Renderer:', prom);
  return prom;
//return result;  
})

Main.js output

渲染器.js

//Invoke Main
let invokeMessage = "ping";
async function send (invokeMessage) {
    console.log('ipcMain.handle response:', window.apiKey.invokeApi('invokeMain', invokeMessage));
//    let response = await window.apiKey.invokeApi('invokeMain', invokeMessage)
//    console.log('ipcMain.handle response:', response);
//    response.then((value) =>{
//        console.log('ipcMain.handle response:', value);
//    });
};
send(invokeMessage);

Renderer.js output

有人可以指出我做错了什么吗?预先感谢

electron preload preloadjs ipcrenderer
1个回答
6
投票

我通过从预加载返回调用方法的承诺而不是值来使其工作。

在我的预载中:

invoke: (channel: string, data: any) => {
    // whitelist channels
    let validChannels = ["myValidChannel"];
    if (validChannels.includes(channel)) {
        return ipcRenderer.invoke(channel, data);
    }
},

并直接在渲染器中处理它:

try {
    const result = await window.myIpcRenderer.invoke("myValidChannel", data)
} catch (err) {
    console.log(err)
}
© www.soinside.com 2019 - 2024. All rights reserved.