背景

由于某个Electron应用,需要主进程、渲染进程、webview之间能够互相通讯。

不过因为Electron仅提供了主进程与渲染进程的通讯,没有渲染进程之间或渲染进程与webview之间通讯的办法,所以只能寻找其他方案来解决。

研究一:ipcMain/ipcRenderer

Electron主进程与渲染进程的通讯,就是用ipcMain/ipcRenderer这两个对象。

// 在主进程中.
const { ipcMain } = require('electron')
ipcMain.on('asynchronous-message', (event, arg) => {
console.log(arg) // prints "ping"
event.reply('asynchronous-reply', 'pong')
}) ipcMain.on('synchronous-message', (event, arg) => {
console.log(arg) // prints "ping"
event.returnValue = 'pong'
}) //在渲染器进程 (网页) 中。
const { ipcRenderer } = require('electron')
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // prints "pong" ipcRenderer.on('asynchronous-reply', (event, arg) => {
console.log(arg) // prints "pong"
})
ipcRenderer.send('asynchronous-message', 'ping')

不过只能ipcRenderer主动发送消息,ipcMain无法主动发送消息给ipcRenderer。

主进程如何主动发送消息给渲染进程?

如果渲染进程的窗口是用BrowserWindow打开的,那么可以通过webContents.send主动向窗口发送消息。

let win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL(`file://${__dirname}/index.html`)
win.webContents.on('did-finish-load', () => {
win.webContents.send('ping', 'whoooooooh!')
})

那么如果想主进程主动向渲染进程发送消息,就可以将创建BrowserWindow的逻辑放在主进程里,所有实例都在主进程里维护,那么主动发消息的问题也就解决了。

渲染进程之间如何进行消息通讯?

Electron虽然没有提供渲染进程之间的通讯,但可以通过主进程中转来达到这个目的。

步骤:

1、ipcRenderer.send消息到主进程。

2、主进程接收到消息,再通过维护的BrowserWindow实例,轮询webContents.send给各个窗口。

3、渲染进程触发订阅主进程事件。

渲染进程与webview之间如何通讯?

由于被打开渲染窗口中,会使用到webview标签(类似iframe)嵌入页面,所以这里也需要互相通讯。

webview是一个标签,它有一个ipc-message事件接收渲染进程的消息,如下。

// In embedder page.
const webview = document.querySelector('webview')
webview.addEventListener('ipc-message', (event) => {
console.log(event.channel)
// Prints "pong"
})
webview.send('ping’) //在访客页。
const { ipcRenderer } = require('electron')
ipcRenderer.on('ping', () => {
ipcRenderer.sendToHost('pong')
})

必须明确一点的是,上面代码中webview监听ipc-message事件的代码是写在渲染进程中的,不是在webview自己页面代码里。这就有一个很尴尬的问题,事件是有了,但webview页面里并不知道。

经过几番尝试,确实无法在嵌入页面接收到事件。

结论

在Electron提供的功能里,只能做到主进程和渲染进程的互相通信,webview像个弃子一样被隔离开了。

研究二:c++插件

上一个方案走不通后,我又想到是否可以做一个c++插件来实现。

PS:http://nodejs.cn/api/addons.html

c++插件实现思路:

1、在插件里定义两个方法,一个listen(订阅事件),一个trigger(发布事件)。

2、在listen里,将订阅事件的上下文(Local<Context>)、事件名称、回调保存下来。

3、在trigger里,遍历保存的订阅信息,匹配事件名称,然后调用订阅信息中的回调。

这里关键的思想就是,在插件有个全局变量来保存各个进程的订阅信息,所有的进程都使用同一个实例对象(单例)。

但是在require插件时候,我发现每个进程都是各自一个实例,不是单例,做不到共享全局变量。

结论

因为require插件的实例不是单例,所以此方案也夭折了。

研究三:socket

在上面方法验证走不通后,最后选择socket方式来中转消息。

PS:https://www.npmjs.com/package/ws

//in main process
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8888 }); wss.on('connection', function connection(ws) {
ws.on('message', function incoming(data) {
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
});
}); //in render process or webview
const WebSocket = require('ws');
const busClient = new WebSocket('ws://127.0.0.1:' + busPort + '/'); busClient.on('message', function incoming(data) {
console.log(data)
}); busClient.send('hello world’);

事件订阅与发布就可以基于上面代码实现。

//in render process or webview
var busEvents = {}; const WebSocket = require('ws');
const busClient = new WebSocket('ws://127.0.0.1:' + busPort + '/'); busClient.on('message', function incoming(data) {
data = JSON.parse(data);
if(busEvents[data.eventName]){
busEvents[data.eventName].apply(this, data.args);
}
}); function listen(eventName, func) {
busEvents[eventName] = func;
} function trigger(eventName, args) {
busClient.send(JSON.stringify({
eventName,
args
}))
}

总结

Electron主进程、渲染进程、webview之间的通讯,只能通过socket实现。

本文为原创文章,转载请保留原出处,方便溯源,如有错误地方,谢谢指正。

本文地址 :http://www.cnblogs.com/lovesong/p/11180336.html

研究Electron主进程、渲染进程、webview之间的通讯的更多相关文章

  1. 使用electron进行原生应用的打包(2)---主进程与渲染进程之间的通信

    上一篇讲了使用electron进行打包的配置相关文件,这篇主要讲electron中很重要的通信方式. 首先解释一个概念: electron打包的应用包含两个部分 electron的环境(node),也 ...

  2. electron 主进程,和渲染进程的通信

    ipcMain https://electronjs.org/docs/api/ipc-main 当在主进程中使用时,它处理从渲染器进程(网页)发送出来的异步和同步信息, 当然也有可能从主进程向渲染进 ...

  3. 17-7-20-electron中主进程和渲染进程区别与通信

    老规矩,先吐槽,再记录. 今天被上司教育了将近一个小时.因为之前自动更新的模块,我认为已经完成了,但是还有一些细节没有完善好,就一直一直的被教育~ 事情全部做完,提交以后关闭issue! electr ...

  4. Visual Studio Code调试electron主进程

    Visual Studio Code调试electron主进程 作者: jekkay 分类: electron 发布时间: 2017-06-11 14:56  一·概述 此文原出自[水滴石]: htt ...

  5. Electron结合React,在渲染进程中使用 node 模块

    Electron结合React,在渲染进程中使用 node 模块 问题 将create-react-app与electron集成在了一个项目中.但是在React中无法使用electron.当在Reac ...

  6. Android 跨进程渲染

    本项目用于验证 Android 是否能够跨进程渲染 View,最终实现了在子进程创建WebView,主进程显示的功能. 一.跨进程渲染的意义 有一些组件比如 WebView 如果在主进程初始化,会大大 ...

  7. C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 VC中进程与进程之间共享内存 .net环境下跨进程、高频率读写数据 使用C#开发Android应用之WebApp 分布式事务之消息补偿解决方案

    C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing). ...

  8. Java线程与线程、进程与进程之间通信方式

    1.1 基本概念以及线程与进程之间的区别联系 关于进程和线程,首先从定义上理解就有所不同: 进程是具有一定独立功能的程序.它是系统进行资源分配和调度的一个独立单位,重点在系统调度和单独的单位,也就是说 ...

  9. Python并发编程03 /僵孤进程,孤儿进程、进程互斥锁,进程队列、进程之间的通信

    Python并发编程03 /僵孤进程,孤儿进程.进程互斥锁,进程队列.进程之间的通信 目录 Python并发编程03 /僵孤进程,孤儿进程.进程互斥锁,进程队列.进程之间的通信 1. 僵尸进程/孤儿进 ...

随机推荐

  1. DataTemplate

    DataTemplate作用是布局+数据绑定 使用DataTemplate 同时完成样式布局和数据绑定 <Window.Resources> <DataTemplate x:Key= ...

  2. Java 知识笔记 - 类、集合、多线程、IO、JVM(最后一次更新,2019年02月17日)

    目录 Class 内部类.静态内部类.匿名内部类.局部内部类 Collection Java Collection Set Queue Map Collections Arrays System Co ...

  3. 创建 DLL 步骤 和 SRC

    LIBRARY SimulationTouchDll EXPORTS MouseControl GetPosition //MouseControlInterface.def 文件 #pragma o ...

  4. 使用WinDug工具调试c#程序或c++程序的dmp崩溃文件,调试内存泄漏

    1.调试c#程序内存泄漏步骤 设置symbol符号路径: SRV*c:\mysymbol* http://msdl.microsoft.com/download/symbols;d:/你的pdb文件路 ...

  5. C#连接oracle 数据库查询时输入中文查询不出来,用plsql就可以

    查询语句为:select * from Per where khmc like '%李%',其实是字符集的问题. 解决方案:在连接字符串加一个“Unicode=True;”

  6. Android零基础入门第59节:AnalogClock、DigitalClock和TextClock时钟组件

    原文:Android零基础入门第59节:AnalogClock.DigitalClock和TextClock时钟组件 在前面一期,我们学习了DatePicker和TimePicker,在实际开发中其不 ...

  7. Spring MVC的工作原理,我们来看看其源码实现

    前言 开心一刻 晚上陪老丈人吃饭,突然手机响了,我手贱按了免提……哥们:快出来喝酒!哥几个都在呢!我:今天不行,我现在陪老丈人吃饭呢.哥们:那你抓紧喝,我三杯白酒,把我岳父放倒了才出来的,你也快点.看 ...

  8. 三种扩展 Office 软件功能的开发模型对比 – Office Add-In Model, VBA 和 VSTO

    当 Office 用户需要针对文档自定义新功能时,可以求助于 VBA 或者 VSTO 两种方式.Office 2013 富客户端以后,微软为 Office 平台上的开发者提供了一种新模型 --- Of ...

  9. 去除文件属性(使用SetFileAttributes API函数)

    FILE_ATTRIBUTE_ARCHIVE 文件存档(备份或移动时会对文件做标记).FILE_ATTRIBUTE_ENCRYPTED 加密(对文件来说是内容加密,对目录来说是对将来新建的文件默认为加 ...

  10. SetWinEventHook 事件钩子(有些windows事件并没有消息对应,譬如弹出菜单,切换窗口,获得焦点,滚动条滚动等)good

    相信消息钩子大家听的比较多,消息钩子能够在应用程序处理系统消息之前将其截获,提前处理并可以决定是否继续将消息往下传送,有些windows事件并没有消息对应,譬如弹出菜单,切换窗口,获得焦点,滚动条滚动 ...