【问题标题】:Send sync message from IpcMain to IpcRenderer - Electron将同步消息从 IpcMain 发送到 IpcRenderer - Electron
【发布时间】:2018-05-15 19:55:16
【问题描述】:

electron 中,可以通过ipcRenderer.sendSync('synchronous-message', 'ping') 将同步消息从IpcRenderer 发送到IpcMain。

也可以使用window.webContents.send('ping', 'whoooooooh!')async消息从IpcMain发送到IpcRenderer

但是有什么方法可以将 sync 消息从 IpcMain 发送到 IpcRenderer?

【问题讨论】:

  • 我相信你不能,因为你会以这种方式阻塞主节点线程,它也运行渲染器进程。但我想你可以通过在渲染器回调中回复 event.sender.send 并在 main 中等待,以异步方式实现同​​样的效果

标签: node.js electron


【解决方案1】:

ipcMain* 没有这样的功能。但是,您可以通过以下步骤异步获得几乎相同的结果:

  • 将仅在同步调用之后运行的代码放在ipcMain 回调中。
  • 使用event.sender.send回复渲染器进程中的ipc消息并返回结果

使用这种方法的 sum 虚拟示例如下所示:

main.js

const {app, BrowserWindow, ipcMain} = require('electron')
const path = require('path')

app.once('ready', () => {
  let win = new BrowserWindow()
  // have to run "sync", that is only after result is ready
  const doJobWithResult = (res) => {
    console.log(res)
  }
  win.webContents.once('dom-ready', () => {
    win.webContents
    .send('sum-request', 23, 98, 3, 61)
    ipcMain.once('sum-reply', (event, sum) => {
      doJobWithResult(sum)
    })
  })
  win.loadURL(path.resolve(__dirname, 'test.html'))
})

renderer.js(引用自 test.html)

const {ipcRenderer} = require('electron')

window.onload = () => {
  const add = (a, b) => {
    return a + b
  }
  ipcRenderer.on('sum-request', (event, ...args) => {
    event.sender.send('sum-reply', [...args].reduce(add, 0))
  })
}

* 我想这是因为从 main 同步调用到渲染器会阻塞主 nodejs 进程,毕竟它也服务于渲染器进程。

【讨论】:

  • 为了避免 doJobWithResult 回调并按顺序排列,我建议这样做: async function sum(...args) { win.webContents.send('sum-request', ...参数); return await = new Promise((resolve) => { ipcMain.once('sum-reply', (event, sum) => { resolve(sum); }) }); } // 先做一些事情 console.log(sum(23, 98, 3, 61)); // 接下来做一些事情这是我用来模拟这个缺失的模式 win.webContents.sendSync
【解决方案2】:

在渲染器进程中访问主进程对象的最简单方法(同步)

// In renderer process (web page).
const { ipcRenderer } = require('electron');
let exec = eval => ipcRenderer.sendSync('synchronous-message', eval);
exec("win.setSize(500,500)");
console.log(exec("win.getBounds()"));
console.log(exec("app.getVersion()"));

// In the Main process.
ipcMain.on('synchronous-message', (event, arg) => {
  event.returnValue = eval(arg);
})

这是从主进程向渲染进程发送消息的方式。(官方示例)

// In renderer process (web page).
ipcRenderer.on('test', (event, arg) => {
    console.log(arg) // 123
})
// In the Main process.(after loaded you can send msg to renderer process)
win.webContents.on('did-finish-load', () => {
    win.webContents.send('test',123);
})

【讨论】:

  • 我想指出,允许来自渲染器进程的未经处理的输入在主进程中运行是一个巨大的安全风险。如果您要加载任何网页,您很容易以远程代码执行结束......
【解决方案3】:

我试图做同样的事情,我得到的最接近的方法是首先从 IPCRenderer 发送消息,然后从收到的 IPCMain 事件中返回您想要的内容,使用以下代码 sn-p:

// In renderer process (web page).
const ipcRenderer = require('electron').ipcRenderer;
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')); // prints "pong"

// In the Main process.
ipcMain.on('synchronous-message', function(event, arg) {
  console.log(arg);  // prints "ping"
  event.returnValue = 'pong';
});

【讨论】:

    【解决方案4】:

    是的,可以将发送同步消息从 IpcRenderer 发送到 IpcMain

    let {ipcRenderer} = require('electron');
    
    ipcRenderer.sendSync('sync', 'Im the message from the renderer');
    
    
    // Listen for sync message from renderer process
    ipcMain.on('sync', (event, arg) => {  
        console.log(arg);   // Print Im the message from the renderer
    });
    

    我建议您访问 VJEKOSLAV RATKAJEC 的这篇文章,他很好地解释了 de ipcMain 与 ipcRenderer 之间的通信,反之亦然。

    链接:http://electron.rocks/different-ways-to-communicate-between-main-and-renderer-process/

    【讨论】:

    • 问题是如何从 ipcMain 发送到 ipcRenderer。您所描述的是默认行为。
    • 对不起Wibby,事情是他们改变了这个问题的主题或问题,我稍后会解决它。
    猜你喜欢
    • 2018-12-29
    • 2021-08-01
    • 2019-08-11
    • 2018-10-03
    • 2020-11-11
    • 2021-07-22
    • 2021-09-13
    • 2021-11-29
    • 1970-01-01
    相关资源
    最近更新 更多