记一次遇到的问题,我们知道Electron 中主进程是在node环境中,所以打算在node环境中再启动一个node服务。但是直接使用exec命令启动就会卡主。对应的代码如下
// 启动Node server
const startServer = async () => {
try {
console.log('开始启动node server');
execSync('npm run server');
console.log('成功启动node server')
} catch (error) {
console.log(`启动node server 失败:${error.message}`)
}
}
// electron 中的main.js
// 这段程序将会在 Electron 结束初始化
app.whenReady().then(async () => {
createWindow()
startServer()
app.on('activate', () => {
// 在 macOS 系统内, 如果没有已开启的应用窗口
// 点击托盘图标时通常会重新创建一个新窗口
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
// watchProtocol()
})
在electron 应用启动之后,会调用startServer方法,在这个方法中会使用exec执行npm run server命令,这个命令会启动一个koa的node 服务。然后启动electron
但是会发现electron应用的窗口没有正常打开,但这个node 服务已近启动起来了。并且可以正常提供接口服务
后来发现是应为使用了同步的命令导致的,只需要把execSync命令缓存exec或者是spawn就可以解决了。
// 启动Node server
const startServer = async () => {
try {
console.log('开始启动node server');
// 使用spawn or exec来启动node服务
//const serverProcess = spawn('node', ['startServer.js']);
exec('npm run server');
console.log('成功启动node server')
} catch (error) {
console.log(`启动node server 失败:${error.message}`)
}
}
之所以同步的命令不行,改成异步的命令就可以。我想是因为在同步命令中,主进程创建的子进程会一直等待子进程的返回。如果子进程的返回很大,会把子进程的返回暂时存在内存中,直至子进程所有内容全部结束后一起返回给主进程。这是node 同步创建子进程的机制,但这里是启动一个服务,本身没有返回的内容。所以主进程就一直在等着子进程的返回。所以electron主进程就卡主了。而通过异步创建的子进程机制则不是这样。通过异步创建的子进程互已返回一个子进程的实例,在这个实例中有stdout、stderr这些标准输出和错误。主进程是通过监听这些事件来获取子进程中返回的信息。并且是子进程产生一部分信息就返回给主进程一部分信息。而不是主进程一直在等着子进程一起返回。所以这里就不会把主进程给阻塞住。主进程通过异步创建子进程获取子进程信息类似下面这样:
const childProcess = spawn('node', ['startServer.js'])
childProcess.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
childProcess.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});
childProcess.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});