问题
在使用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);
这样就可以在子窗口中进行计算,并且回调结果了~