electron教程(二): http服務器, ws服務器, 子進程管理


我的electron教程系列

electron教程(一): electron的安裝和項目的創建

electron教程(番外篇一): 開發環境及插件, VSCode調試, ESLint + Google JavaScript Style Guide代碼規范

electron教程(番外篇二): 使用TypeScript版本的electron, VSCode調試TypeScript, TS版本的ESLint

electron教程(二): http服務器, ws服務器, 子進程管理

electron教程(三): 使用ffi-napi引入C++的dll

electron教程(四): 使用electron-builder或electron-packager將項目打包為可執行桌面程序(.exe)

 

引言

 

這次, 我們一起通過幾個例子, 進一步了解node.js+electron.

 

三個例子:

 

1.  搭建一個http服務器, 通過web對服務器進行訪問
  2.  搭建一個ws服務器, 通過web向服務器發送消息
  3.  進程管理, 打開/關閉一個外部進程

 

例子1: 一個http服務器

 

1. 部署node.js+electron環境

按步驟完成electron教程(一): electron的安裝和項目的創建所介紹的內容.

 

2. 安裝http-server

確保你的cmd工作目錄為項目根目錄.

執行指令:

yarn add http-server --save

 

3. 在main.js中添加http服務器

在main.js的最下方, 添加如下代碼:

// http-server
const httpServer = require('http-server');

httpServer.createServer().listen(8080);

在這段代碼中:

我們創建了一個httpServer對象

const httpServer = require('http-server');

這個對象是通過http-server模塊創建出來的.

使用httpServer對象, 創建一個http服務器, 並且監聽了8080端口.

服務器啟動后, 用戶就可以通過瀏覽器來訪問我們的服務器了.

 

4. 啟動程序!

執行指令:

npm start

在自己的瀏覽器中,訪問http://localhost:8080/index.html,就會得到本地的index.html文件

(這是chrome瀏覽器打開的效果)

 

例子2: 一個ws服務器

 

1. 部署node.js+electron環境

node.js+electron教程(一): 安裝nodejs和electron

 

2. 安裝ws

確保你的cmd工作目錄為項目根目錄.
執行指令:

yarn add ws --save

 

3. 在main.js中添加ws服務器

在main.js的最下方, 添加如下代碼:

// ws-服務器
const WebSocketServer = require('ws').Server;
wss = new WebSocketServer({port: 12122});
wss.on('connection', (ws) => {
  // 有客戶端連接時, 打印一條日志
  console.log('client connected');
  // 並且創建'message'監聽
  ws.on('message', (message) => {
    // 直接將消息打印出來
    console.log(message);
  });
});

在這段代碼中:

我們創建了一個WebSocketServer對象

const WebSocketServer = require('ws').Server;

這個對象是通過ws模塊創建出來的.

使用WebSocketServer對象, 創建一個ws服務器叫做wss對象, 並且監聽了12122端口.

為wss對象的兩個事件分別綁定了回調:

connection事件, 有客戶端連接時, 打印一條日志.

message事件, 直接將消息打印出來.

 

4. 在index.html中引入jquery

jquery官網下載jquery庫, 將jquery.min.js放在html目錄下的lib目錄中.

並在index.html的<head></head>塊中, 添加如下代碼:

<script type="text/javascript" src="./lib/jquery.min.js"></script>

 

5. 在index.html中, 添加一個輸入框和按鈕

在index.html的<body></body>塊中的最下方, 添加如下代碼:

<div class="vertical-center">
    <div class="container">
        <p>&nbsp;</p>
        <form role="form" id="chat_form" onsubmit="sendWsMessage(); return false;">
            <div class="form-group">
                <input class="form-control" type="text" name="message" id="message"
                       placeholder="Type text to echo in here" value="" />
            </div>
            <button type="button" id="send" class="btn btn-primary"   
                    onclick="sendWsMessage();"> 
                Send!
            </button>
        </form>
    </div>
</div>

在這段代碼中:

我們首先定義了一個輸入框即表單form, 該表單包含了input元素, 用戶可以在該輸入框內填寫字符, 而html可以通過message來獲取輸入框內的字符.

接着我們定義了一個按鈕button, 在網頁中按鈕顯示為send!, 並給該按鈕的左鍵點擊事件onclick綁定了一個函數onclick="sendWsMessage();", 當用戶左鍵點擊這個send!按鈕, 就會觸發sendWsMessage()函數.

 

6. 在index.html中, 定義ws客戶端

在index.html的<script></script>塊中的最下方, 添加如下代碼:

const ws = new WebSocket("ws://localhost:12122");

這段代碼中:

我們先實例化了一個websocket對象ws, 其參數為要連接的地址, 這里使用本機localhost的12122端口, 如果你是在局域網內啟動, 也可以將localhost替換為你的內網ip.

 

7. 在index.html中, 定義按鈕的sendWsMessage()函數

在index.html的<script></script>塊中的最下方, 添加如下代碼:

function sendWsMessage() {
  ws.send($('#message').val());
}

這段代碼中:
我們調用了websocket對象wssend()方法, 向目標地址localhost的12122端口發送數據, 數據的內容是通過#message獲取的, 即用戶在輸入框內輸入的數據.

前端流程:

當用戶點擊send!按鈕, 獲取輸入框內的內容, 通過ws, 向localhost的12122端口發送.

 

8. 啟動

執行指令:

npm start

此時的程序界面, 出現了輸入框send!按鈕.

 

回到cmd中, 發現cmd打印了一條日志

client connected

那是因為我們在ws服務器(main.js)中, 添加了如下代碼:

wss.on('connection', (ws) => {
  // 有客戶端連接時, 打印一條日志
  console.log('client connected');

當程序啟動的時候, 自動建立了連接, 所以打印了這條日志.

如果你已經完成了例子1, 並且還沒有刪除代碼的話, 試着再次從瀏覽器中訪問http://localhost:8080/index.html, 是否又打印出了一條相同的日志?

 

現在, 我們試試發送消息的功能:

在程序界面的輸入框內, 輸入一個Hello electron!, 點擊send!

回到cmd中, 成功打印了日志Hello electron!.

 

前端流程:

當用戶點擊send!按鈕, 獲取輸入框內的內容, 通過ws, 向localhost的12122端口發送.

后端流程:

當ws服務器收到消息的時候, 直接將消息打印出來.

 

例子3: 進程管理

 

1. 部署node.js+electron環境

node.js+electron教程(一): 安裝nodejs和electron

 

2. 在main.js中, 啟動一個外部進程

在main.js中, 添加如下代碼:

const myChildProccess = require('child_process');

// 打開一個子進程notepad++
const mySpawn = myChildProccess.spawn(
    'e:\\Application\\Notepad++\\notepad++.exe');

在這段代碼中:

我們創建了一個myChildProccess對象

  const myChildProccess = require('child_process');

這個對象是通過child_process模塊創建出來的, 該模塊主要用於創建子進程.

我們調用這個對象的spwan()方法, 啟動一個子進程. 該方法接受一個字符串參數, 是子進程的路徑, 注意路徑的書寫方式.

 

3. 測試

執行命令:

npm start

在程序啟動后, notepad++也緊跟着啟動了, notepad++就是本程序啟動的子進程.

electron可以啟動子進程, 自然也可以關閉子進程, 不然算什么進程管理?

 

現在我們關閉程序, 繼續進行下一步.

 

4. 在index.html中, 添加一個按鈕, 關閉子進程

在index.html的<body></body>塊中的最下方, 添加如下代碼:

<button onclick="killChildProcess()">關閉子進程</button>

在這段代碼中, 我們添加了一個按鈕button, 在網頁中按鈕顯示為關閉子進程, 並給該按鈕綁定了一個函數killChildProcess().

 

5. 創建renderer.js, 並添加到項目中

在html目錄創建一個renderer.js文件

添加如下代碼:

function killChildProcess() {
  // 發消息,由html的按鈕調用,給主進程發消息,回調中關閉進程
  const ipcRenderer = require('electron').ipcRenderer;
  ipcRenderer.send('kill-child-now', 'get async message');
}

我們定義了關閉子進程按鈕的點擊函數killChildProcess(), 這個函數只有兩行:

在函數的第一行, 創建了一個ipcRenderer對象

  const ipcRenderer = require('electron').ipcRenderer;

這個對象是通過ipcRenderer模塊創建出來的, w3cschool是這樣解釋的:

ipcRenderer 模塊是一個 EventEmitter 類的實例. 它提供了有限的方法,你可以從渲染進程向主進程發送同步或異步消息. 也可以收到主進程的響應.

簡單的說, main.js是主進程, renderes.js是渲染進程, 在渲染進程調用ipcRenderer.send()方法, 可以發送消息. 在主進程可以收到消息, 如果你給這個消息綁定了回調, 收到消息后, 就會觸發回調.

 

在函數的第二行, 我們發送了kill-child-now消息.

現在我們把renderer.js引入到項目之中

jquery相似, 在index.html的<head></head>塊中, 添加如下代碼:

<script type="text/javascript" src="../dist/renderer.js"></script>

 

6. 在main.js中, 監聽消息, 綁定回調

在main.js的最下方, 添加如下代碼:

// 監聽消息, 關閉子進程
const ipcMain = require('electron').ipcMain;

ipcMain.on('kill-child-now', (e, appUrl)=>{
  // 收到消息, 關閉進程
  mySpawn.kill();
});

在這段代碼中:

我們創建了一個ipcMain對象

const ipcMain = require('electron').ipcMain;

這個對象是通過ipcMain模塊創建出來的, w3cschool是這樣解釋的:

ipcMain 模塊是類 EventEmitter 的實例.當在主進程中使用它的時候,它控制着由渲染進程(web page)發送過來的異步或同步消息.從渲染進程發送過來的消息將觸發事件.

簡單的說, ipcMain是使用在主進程中的, 負責監聽從渲染進程中發送出來的消息.

( 還記得嗎? 渲染進程是通過ipcRenderer發送消息的. )

我們用ipcMain對象監聽了消息kill-child-now, 並且綁定了一個回調函數. 一旦收到這個消息, 就會觸發這個回調函數.

回調函數只有一行, 簡單直接:

mySpawn.kill( )

關閉在第三步中創建的子進程notepad++.

 

7. 啟動

執行命令:

npm start

和之前的測試一樣, 在程序啟動后, notepad++也緊跟着啟動了, notepad++就是本程序啟動的子進程.

不一樣的是, 程序界面上出現了一個按鈕關閉子進程.

點擊這個按鈕試試看!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM