關於electron在主進程阻塞的情況下ui會卡頓的問題

問題

在使用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);

這樣就可以在子窗口中進行計算,並且回調結果了~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章