主进程与渲染进程
Electron 中,从 package.json 的 main 载入的 js 件就是主进程,由主进程加载出来的页面就是渲染进程。
主进程负责掌管所有的 Web 页面和它们相应的渲染进程,包括原生的组件操作。而在 Electron 里的每个页面都有它自己的进程,叫作渲染进程,它主要负责 Web 的渲染。
主进程通过实例化 BrowserWindow,每个 BrowserWindow 实例都在它自己的渲染进程内返回一个 web 页面。当 BrowserWindow 实例销毁时,相应的渲染进程也会终止。
在渲染进程中不允许调用原生 GUI 相关的 API,那是因为在网页(渲染进程)中使用原生 GUI 很危险,易造成内存泄露。
利用 ipcMain 与 ipcRenderer 通信
ipcMain 模块是类 EventEmitter 的实例。当在主进程中使用它的时候,它控制着由渲染进程发送过来的异步或同步消息,从渲染进程发送过来的消息将触发事件,同样也可以从主进程向渲染进程发送消息,事件的对称的。
因此,可以通过事件的订阅或与发布,实现主进程与渲染进程之间的通信。在主进程里,使用 ipcMain 向渲染线程发出通知1
2
3
4
5
6
7
8
9
10
11
12const ipcMain = require('electron').ipcMain;
ipcMain.on('asynchronous-message', function(event, arg){
console.log(arg); // prints "ping"
event.sender.send('asynchronous-reply', 'pong');
});
// 同步通信
ipcMain.on('synchronous-message', function(event, arg){
console.log(arg); // prints "ping"
event.returnValue = 'pong';
});在渲染进程里,使用 ipcRenderer 向主线程发出通知1
2
3
4
5
6
7
8
9
10
11const ipcRenderer = require('electron').ipcRenderer;
// 发一个同步消息给所以 synchronous-message 监听者
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')); // prints "pong"
// 监听
ipcRenderer.on('asynchronous-reply', function(event, arg){
console.log(arg); // prints "pong"
});
// 发一个异步消息给所有 asynchronous-message 监听者
ipcRenderer.send('asynchronous-message', 'ping');
注意的地方,在 ipcMain 里是不能主动向 ipcRenderer 发消息的,只能在 event 里回消息。
ipcMain API
ipcMain 模块有以下方法:ipcMain.on(channel, listener) 监听 channel, 当新消息到达,将通过 listener(event, args…) 调用 listener。
ipcMain.once(channel, listener) 监听一次(一次性)。
ipcMain.removeListener(channel, listener) 取消监听。
ipcMain.removeAllListeners([channel]) 取消全部监听。
而在 listener 里 event 有以下属性:event.returnValue 将此设置为在一个同步消息中返回的值。
event.sender 返回发送消息的 webContents ,你可以调用 event.sender.send 来回复异步消息。
ipcRenderer API
ipcRenderer 模块有以下方法:ipcRenderer.on(channel, listener) 监听 channel, 当新消息到达,将通过 listener(event, args…) 调用 listener。
ipcRenderer.once(channel, listener) 监听一次(一次性)。
ipcRenderer.removeListener(channel, listener) 取消监听。
ipcRenderer.removeAllListeners([channel]) 取消全部监听。
ipcRenderer.send(channel[, arg1][, arg2][, …]) 通过 channel 向主进程发送异步消息,也可以发送任意参数。
ipcRenderer.sendSync(channel[, arg1][, arg2][, …]) 通过 channel 向主进程发送同步消息,也可以发送任意参数。
ipcRenderer.sendToHost(channel[, arg1][, arg2][, …]) 它的事件将发往 host page 的 元素,而不是主进程。
利用 remote 通信
remote 模块提供了一种在渲染进程(网页)到主进程之间进行进程间通讯(IPC)的简便途径。注意: 反向操作(从主进程访问渲染进程),可以使用 webContents.executeJavascript.
Electron 中与 GUI 相关的模块(如 dialog, menu 等)只存在于主进程,而不在渲染进程中。为了能从渲染进程中使用它们,需要用 ipc 模块来给主进程发送进程间消息。使用 remote 模块,可以调用主进程对象的方法,而无需显式地发送进程间消息。
remote 模块返回的每个对象(包括函数)都代表了主进程中的一个对象。
在主进程中的内置模块已经被添加为 remote 模块中的属性,所以可以直接像使用 electron 模块一样直接使用它们。1
2
3
4
5
6// 在渲染进程文件里
const remote = require('electron').remote;
const BrowserWindow = remote.BrowserWindow;
var win = new BrowserWindow({ width: 800, height: 600 });
win.loadURL('https://github.com');
remote API
remote 模块有以下方法:remote.require(module) 返回在主进程中执行 require(module) 所返回的对象。
remote.getCurrentWindow() 返回该网页所属的 BrowserWindow 对象。
remote.getCurrentWebContents() 返回该网页的 WebContents 对象。
remote.getGlobal(name) 返回在主进程中名为 name 的全局变量(即 global[name])。
remote.process 返回主进程中的 process 对象。等同于 remote.getGlobal('process') 但是有缓存。
参考资料