当前位置: 首页 > wzjs >正文

java动态网站开发心得深圳网络推广平台

java动态网站开发心得,深圳网络推广平台,安徽建设局网站,手机网站营销的含义背景 在 electron 开发中,也不可避免地遇到端到端的通信问题,Electron 已经内置一些通信 API,但是实际用下来会发现,在引入 Webview 之后,通信链路会很长,参考 利用本地 Express Web 服务解决复杂的 Elec…

背景

在 electron 开发中,也不可避免地遇到端到端的通信问题,Electron 已经内置一些通信 API,但是实际用下来会发现,在引入 Webview 之后,通信链路会很长,参考  利用本地 Express Web 服务解决复杂的 Electron 通信链路的问题_ipcrenderer.invoke('save-data-CSDN博客的问题, 在这个过程中有一种机制可以有效解决通信链路的问题,这个就是 MessageChannel,MessageChannel 可以提供两个 port,一个自己拿着,另外一个发给别人,以此来实现双向通信,有了这个东西,无论再远的距离,只需要有个中间人帮你把话筒拿给那个人,你们就可以实现互聊。

MessageChannel 在多 iframe 开发上的表现

纯用Grok 实现一个多 iframe 互聊对话框 利用父子框架通信和MessageChannel 实现 n 个 iframe 的动态创建——通用编码习惯-CSDN博客

代码仓库

electron-demo: electron 22 初始代码开发和讲解https://e.gitee.com/sen2020/projects/203933/repos/sen2020/electron-demo/tree/feature%2Fmessageport

feature/messageport 分支

 

Electron 中的概念纠正

  1. Webview 和 Renderer 是同级的,两者只有一个关联关系,也即 Webview 在那个 Renderer 中展现的,Webview 所有运行方式以及通信方式,均与 Renderer 没有任何差别,Webview 可以直接与主进程通信,这个概念特别重要,否则就会绕一大圈,Electron 官网给了一个 sendToHost API,误解性很大,让我们误以为只有 sendToHost 才能与 Webview 依附的渲染通信,然后再中转给其他渲染进程或者 webview 等,实际上完全不需要

  2. 同级这个概念其实在代理拦截,打开外部链接,以及请求头替换等方面都有表现,只是被忽略了

  3. preload.js 代码是被当作一个闭包执行的,如果你在 console 控制台查看时,会发现的确是一个闭包在执行,所以里面的函数和变量你不暴露在 window 上的话,注入 js 是拿不到这些函数,当然前提条件是,去掉上下文隔离。

去掉上下文隔离设置

必备知识

  1. 因为 Electron 主进程是基于 Node.js 环境来运行的,所以并不是 V8 的环境,要想实现类似 Web 环境的 MessageChannel,Electron 就必须自己重新实现,因此 Electron 中的 MessageChannel 类型为 MessageChannelMain,这里为了照顾系统起来后,就会立即推送信息过来,而主进程没有充分启动,导致消息丢失问题,Electron 团队追加了一个 port.start() 函数,也即主进程完全 OK 后,可开启消息消费。

  2. 主进程的MessageChannel 不重要,因为主进程并不创建MessageChannel,只管理来自其他 Renderer 和 Webview 的 channel.port,并将信息进行及时中转,因为所有的其他进程都可以直接联系到主进程,利用 send,invoke,sendSync,postMessage 等 API 都可以与主进程直接通信

  3. Electron 官方很鼓励使用 MessagePort 进行通信,原因是这个通信机制是点对点通信,并不是像监听一样采用广播机制发送消息,在一定意义上对内存的耗费就大大降低了,所以更换 MessagePort 方向是对的

具体实现思路

  1. 在 preload.js 或者任意注入脚本任意位置的组件内部,都可以创建一个 MessageChannel,给自己起一个名字,并把自己注册到主进程去,之后就可以加入到大家庭了

  2. 在渲染进程中的任意一个 Vue 组件里面创建一个 MessageChannel,给自己起个名字,然后注册给主进程,之后就可以加入到大家庭了

  3. 主进程监听来自各个渲染进程和 Webview 组件的 MessageChannel 注册,并实现每个 port 广播和 from to 的中转逻辑即可

实现快照

代码实现

主进程添加以下代码

// 使用 Map 存储 MessagePort,键为名称,值为 MessagePort 对象
const ports = new Map();// 监听渲染进程和 webview 的注册请求
ipcMain.on('register', (event, name) => {const port = event.ports[0]; // 获取传递的 MessagePortif (ports.has(name)) {port.postMessage({type: 'error',data: `Name "${name}" already registered`,});return;}ports.set(name, port);// 监听该 MessagePort 的消息port.on('message', (event) => {const { from, to, data } = event.data;console.log(`Forwarding message from ${from} to ${to}`);if (to === 'all') {// 广播给所有其他 MessagePortports.forEach((p, pName) => {if (pName !== from) {p.postMessage({ from, data });}});} else if (ports.has(to)) {// 转发给指定的 MessagePortports.get(to).postMessage({ from, data });} else {// 目标不存在,发送错误消息ports.get(from).postMessage({type: 'error',data: `Target ${to} not found`,});}});// 监听关闭事件port.on('close', () => {console.log(`${name} 的 MessagePort 已关闭`);ports.delete(name);});// 开始接收消息port.start();// 向注册者发送注册成功消息port.postMessage({ type: 'registered', name });
});

渲染进程添加如下代码,任意位置,代码是通用的,只需要改改 name 即可

// 创建 MessageChannelconst { port1, port2 } = new MessageChannel();const myPort = port2;const myName = "mainWindow"// 将 port1 发送给主进程,附带名称ipcRenderer.postMessage('register', myName, [port1]);// 监听来自主进程的消息myPort.onmessage = (event) => {const { type, from, data } = event.data;console.log(`Received message from ${from}`);if (type === 'registered') {console.log(`注册成功: ${myName}`);} else if (type === 'error') {console.log(`错误: ${data}`);} else {console.log(`[${from}]: ${data}`);}};// 发送消息给另一个进程function sendMessage(to, data) {myPort.postMessage({ from: myName, to, data });}// 发送广播消息function broadcastMessage(data) {myPort.postMessage({ from: myName, to: 'all', data });}window.sendMessage = sendMessage;window.broadcastMessage = broadcastMessage;// 示例用法setTimeout(() => {sendMessage('wb1', 'Hello from renderer1!');broadcastMessage('Broadcast from renderer1!');}, 10000);}

preload.js 中的实现代码,基本和渲染进程是一样的

// 因为WhatsApp也有个require函数,这里会干扰WhatsApp加载
delete window.require; // 这里是node.js环境,必须用require引入
const {ipcRenderer} = require("electron") ; 
// 创建 MessageChannel
const { port1, port2 } = new MessageChannel();
window.myPort = port2;
window.myName = "wb1"// 将 port1 发送给主进程,附带名称
ipcRenderer.postMessage('register', myName, [port1]);// 监听来自主进程的消息
myPort.onmessage = (event) => {const { type, from, data } = event.data;console.log(`Received message from ${from}`);if (type === 'registered') {console.log(`注册成功: ${myName}`);} else if (type === 'error') {console.log(`错误: ${data}`);} else {console.log(`[${from}]: ${data}`);}
};// 发送消息给另一个进程
function sendMessage(to, data) {myPort.postMessage({ from: myName, to, data });
}window.sendMessage = sendMessage;// 发送广播消息
function broadcastMessage(data) {myPort.postMessage({ from: myName, to: 'all', data });
}window.broadcastMessage = broadcastMessage;// 示例用法
setTimeout(() => {sendMessage('mainWindow', 'Hello from renderer1!');broadcastMessage('Broadcast from renderer1!');
}, 2000);

http://www.dtcms.com/wzjs/21470.html

相关文章:

  • 网站建设行业导航站点河南网站建设定制
  • 如何在网站做宣传汽车网站建设方案
  • android网站开发实例谷歌seo代运营
  • 手机网站建设教程免费的网站域名查询565wcc
  • 高大上企业网站搜索seo
  • 网站编辑主要做什么企业微信管理系统
  • 网站建设框架网络营销推广策划的步骤
  • 电脑手机网站建设四川省最新疫情情况
  • 哪里做网站便宜百度网站提交收录入口
  • 网站怎么做是满屏哪些网站可以免费申请域名
  • 宝应县网络推广公司深圳seo优化服务
  • 网站站点怎么做杭州关键词推广优化方案
  • 长沙网站设计服务百度新闻首页新闻全文
  • 网站群建设论文合肥网站制作
  • 青岛 网站建设关键词代发排名
  • 嘉兴网站开发公司建网站建设
  • 做网站的销售怎么样交换友情链接时需要注意的事项
  • 网站如何跟域名绑定湖南百度seo
  • 怎么做网站的301天津seo排名公司
  • 建设银行山西招聘网站网站排名优化需要多久
  • 网站建设百度搜不到杭州最好的seo公司
  • 无锡网站建设培训学校购物网站页面设计
  • 阿克苏网站建设价格品牌营销策略案例
  • wordpress插件微信搜狗seo怎么做
  • 什么网站做跨境电子商务口碑营销的概念
  • 长沙人才招聘网站seo高级教程
  • win7家用电脑做网站服务器自己想做个网站怎么做
  • 中国建设教育网站seo教程网站优化
  • 买了服务器不翻墙就用来 做网站网页设计首页制作
  • wordpress特别版新泰网站seo