日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

electron监听网页_Electron 进程通信

發(fā)布時間:2024/3/26 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 electron监听网页_Electron 进程通信 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本文作者:IMWeb laynechen

未經(jīng)同意,禁止轉(zhuǎn)載

Electron 中的進程分類

在 Electron 中,存在兩種進程:主進程和渲染進程。

主進程 (Main Process)

一個 Electron 應用只有 一個主進程

當我們執(zhí)行 electron . 命令后, Electron 會運行當前目錄(.)下的 package.json 文件中 main 字段指定的文件。而運行該文件的進程既是主進程。

運行在主進程中的腳本可以通過創(chuàng)建一個窗口,并傳入 URL,讓這個窗口加載一個網(wǎng)頁來展示圖形界面。

與創(chuàng)建 GUI 相關的接口只應該由主進程來調(diào)用。

渲染進程 (Renderer Process)

在Electron里的每個頁面都有它自己的進程,叫作渲染進程。主進程通過實例化 BrowserWindow,每個 BrowserWindow 實例都在它自己的渲染進程內(nèi)返回一個 web 頁面。當 BrowserWindow 實例銷毀時,相應的渲染進程也會終止。

渲染進程由主進程進行管理。每個渲染進程都是相互獨立的,它們只關心自己所運行的 web 頁面。

問題

這篇文章主要要解決的問題是:

Electron 與 View 層(網(wǎng)頁),也就是主進程與渲染進程是如何進行通信的?

不同的通信是如何實現(xiàn)的?

先解決第一個問題。

Electron 與 View 層(網(wǎng)頁)是如何進行通信的?

Electron 提供了兩種通信方法:

1. 利用 ipcMain 和 ipcRenderer 模塊

官方文檔 上有使用這兩個模塊進行進程通信的例子:

// In main process.

const {ipcMain} = require('electron')

ipcMain.on('asynchronous-message', (event, arg) => {

console.log(arg) // prints "ping"

event.sender.send('asynchronous-reply', 'pong')

})

ipcMain.on('synchronous-message', (event, arg) => {

console.log(arg) // prints "ping"

event.returnValue = 'pong'

})

// In renderer process (web page).

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 模塊的 send 方法向主進程發(fā)送消息。在主進程中,通過 ipcMain 模塊設置監(jiān)聽 asynchronous-message 和 synchronous-message 兩個事件,當渲染進程發(fā)送時就可以針對不同的事件進行處理。

主進程監(jiān)聽事件的回調(diào)函數(shù)中,會傳遞 event 對象及 arg 對象。arg 對象中保存渲染進程傳遞過來的參數(shù)。通過 event.sender 對象,主進程可以向渲染進程發(fā)送消息。如果主進程執(zhí)行的是同步方法,還可以通過設置 event.returnValue 來返回信息。

上面說了渲染進程如何向主進程發(fā)送消息,但主進程也可以主動向渲染進程發(fā)送消息

在主進程中,我們會創(chuàng)建一個 BrowserWindow 對象,這個對象有 webContents 屬性。webContets 提供了 send 方法來實現(xiàn)向渲染進程發(fā)送消息。當然 webContents 對象遠不止這兩個通信方法,具體可以看 webContents

下面是官方文檔提供的使用 webContents 實現(xiàn)通信的例子:

// In the main process.

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

let win = null

app.on('ready', () => {

win = new BrowserWindow({width: 800, height: 600})

win.loadURL(`file://${__dirname}/index.html`)

win.webContents.on('did-finish-load', () => {

win.webContents.send('ping', 'whoooooooh!')

})

})

console.log(message) // Prints 'whoooooooh!'

})

注意,webContents.on 監(jiān)聽的是已經(jīng)定義好的事件,如上面的 did-finish-load。要監(jiān)聽自定義的事件還是通過 ipcMain 和 ipcRenderer。

渲染進程的監(jiān)聽事件回調(diào)函數(shù)中,也可以通過 event.sender 來向主進程發(fā)送消息。這個對象只是 ipcRenderer 的引用(event.sender === ipcRenderer)。因此,event.sender 發(fā)送的消息在主進程中還是需要通過 ipcMain.on 方法來監(jiān)聽,而不是通過 webContents.on 方法。

2. 利用 electron.remote 模塊

在渲染進程中,可以通過

const { remote } = require('electron');

獲取到 remote 對象,通過 remote 對象可以讓渲染進程訪問/使用主進程的模塊。例如,通過 remote 在渲染進程中新建一個窗口:

const {BrowserWindow} = require('electron').remote

let win = new BrowserWindow({width: 800, height: 600})

win.loadURL('https://github.com')

同樣的,我們也可以通過 remote 對象訪問到 app 對象。這樣我們就可以訪問到我們在主進程中掛載到 electron.app 對象上的方法。

如:

main.js 文件:

// In main process

const { app } = require('electron');

const utils = require('./utils');

app.utils = utils; // 將在 Electron 層實現(xiàn)的接口綁定到 app 上

index.js 文件(被網(wǎng)頁引用的腳本文件):

const { remote } = require('electron');

// In renderer process

function(){

// remote.app.utils 對象與上述文件中的 utils 對象是一樣的。

remote.app.utils.test();

}

Electron 的兩種進程通信方法是如何實現(xiàn)的?

知道怎么用還不夠,還需要了解 Electron 是如何實現(xiàn)這兩種通信方法的,以及 Electron 為什么要實現(xiàn)兩種通信方法,這兩種通信方法的有什么不同的地方。弄清楚這些開發(fā)起來才會對程序的數(shù)據(jù)流比較清晰。

ipcMain 和 ipcRenderer

The ipcMain module is an instance of the EventEmitter class. When used in the main process, it handles asynchronous and synchronous messages sent from a renderer process (web page). Messages sent from a renderer will be emitted to this module.

ipcMain 和 ipcRenderer 都是 EventEmitter 類的一個實例。而 EventEmitter 類由 NodeJS 中的 events 模塊導出。

events.EventEmitter

EventEmitter 類是 NodeJS 事件的基礎,實現(xiàn)了事件模型需要的接口, 包括 addListener,removeListener, emit 及其它工具方法. 同原生 JavaScript 事件類似, 采用了發(fā)布/訂閱(觀察者)的方式, 使用內(nèi)部 _events 列表來記錄注冊的事件處理器。

我們通過 ipcMain和ipcRenderer 的 on、send 進行監(jiān)聽和發(fā)送消息都是 EventEmitter 定義的相關接口。

那么 ipcMain 和 ipcRenderer 是如何實現(xiàn)這些接口的呢?

ipc-renderer.js

const binding = process.atomBinding('ipc')

...

// Created by init.js.

const ipcRenderer = v8Util.getHiddenValue(global, 'ipc')

ipcRenderer.send = function (...args){

return binding.send('ipc-message', args)

}

....

module.exports = ipcRenderer

調(diào)用了 atomBinding('ipc') 得到的 binding 對象的 send 方法。能力有限,就分析到這。后面 binding.send 應該就是 IPC 相關的實現(xiàn)了:對傳送的數(shù)據(jù)進行序列化和反序列化。

// 主進程

ipcMain.on('test1', (e) => {

const obj = {};

obj.toJSON = () => 'call toJSON';

e.returnValue = obj;

})

ipcMain.on('test2', (e) => {

const obj = { name: '123' };

e.returnValue = obj;

})

// 渲染進程

let returnValue = ipcRenderer.sendSync('test1');

console.log(typeof returnValue, returnValue); // 'string call toJSON'

returnValue = ipcRenderer.sendSync('test2');

console.log(typeof returnValue, returnValue); // 'object Object name: "123"__proto__: Object'

從渲染進程輸出的消息可以看到,主進程將返回值調(diào)用 toJSON 后傳遞給渲染進程。渲染進程再對傳輸過來的內(nèi)容進行反序列化。

remote 遠程對象

通過 remote 對象,我們可以不必發(fā)送進程間消息來進行通信。但實際上,我們在調(diào)用遠程對象的方法、函數(shù)或者通過遠程構造函數(shù)創(chuàng)建一個新的對象,實際上都是在發(fā)送一個同步的進程間消息(官方文檔 上說這類似于 JAVA 中的 RMI)。

也就是說,remote 方法只是不用讓我們顯式的寫發(fā)送進程間的消息的方法而已。在上面通過 remote 模塊創(chuàng)建 BrowserWindow 的例子里。我們在渲染進程中創(chuàng)建的 BrowserWindow 對象其實并不在我們的渲染進程中,它只是讓主進程創(chuàng)建了一個 BrowserWindow 對象,并返回了這個相對應的遠程對象給了渲染進程。

參考資料

總結

以上是生活随笔為你收集整理的electron监听网页_Electron 进程通信的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。