問題
在使用electron的過程中可能會出現這樣的問題:
在我回調一個方法,比如child_process.spawn()的時候,我設計的等待動畫不會出問題,在計算結束後等待動畫也會結束,但是當我使用child_process.spawn()時就會出現動畫進程不進行的情況。
參考Electron的主進程阻塞導致UI卡頓的問題這篇文章,我大概瞭解了electron的渲染方式:
實際的原因正是和其中的IPC有關,在chromium中,頁面渲染時,UI進程需要和main process不斷的進行sync IPC,若此時main process忙,則UI process就會在IPC時阻塞。
由於js是單線程的,在執行函數時如果遇到重cpu任務時就會造成主進程阻塞的情況。
解決方法
那麼該如何解決呢?我們可能會想既然異步的回調不會造成阻塞,爲什麼我們不都使用異步呢?
當接口是回調函數的時候當然沒有問題,但是有些函數提供的api是同步的,如何解決這個問題?
這時候我們可以使用electron提供的window窗口功能,在需要執行的時候提前創建好一個透明窗口用來執行重cpu任務。當執行完成的時候通過ipc進行進程的通訊。
舉個栗子:
//demo.js
function click() {
const windowID = BrowserWindow.getFocusedWindow().id
const invisPath = 'remote.html'
let win = new BrowserWindow({
width: 400,
height: 400,
show: false,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile(invisPath);
win.webContents.on('did-finish-load', () => {
var par;
win.webContents.send('compute-vis', par, windowID);
})
});
ipcRenderer.on('vis-computed', (event, output) => {
console.log(output);
})
<!--remote.html-->
<html>
<script type="text/javascript">
const ipc = require('electron').ipcRenderer
const BrowserWindow = require('electron').remote.BrowserWindow
const child_process = require('child_process');
ipc.on('compute-vis', function (event, par, fromWindowId) {
const result = visBuilding(par)
const fromWindow = BrowserWindow.fromId(fromWindowId)
fromWindow.webContents.send('vis-computed', result)
window.close()
})
function visBuilding(par) {
return par;
}
</script>
</html>
其中加載html的方法有兩種:
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}));
// or
invisPath=path.join(__dirname, 'index.html');
mainWindow.loadFile(invisPath);
這樣就可以在子窗口中進行計算,並且回調結果了~