Electron中启动node服务

在Electron应用中,尝试使用execSync启动Node服务导致应用窗口无法正常打开。问题在于execSync是同步命令,会阻塞主进程。改用异步命令如exec或spawn,通过监听子进程的事件来处理输出,避免了主进程被阻塞,从而解决了问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

记一次遇到的问题,我们知道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}`);
  }); 
### 启动后台服务或进程 在 Electron 应用程序中启动后台服务或进程通常是在主进程中完成。通过 Node.js 提供的强大 API 可以轻松实现这一目标。对于需要长时间运行的任务或是独立于主线程的服务,可以利用 `child_process` 模块来创建子进程。 下面是一个简单的例子,在主进程中使用 `fork()` 方法启动一个新的 JavaScript 文件作为子进程: ```javascript const { fork } = require('child_process'); // 创建子进程并传递参数给它 let workerProcess = fork('./worker.js', ['arg1']); // 接收来自子进程的消息 workerProcess.on('message', (msg) => { console.log('Message from child:', msg); }); // 发送消息到子进程 workerProcess.send({ hello: 'world' }); // 子进程退出事件监听器 workerProcess.on('close', (code) => { console.log(`Child process exited with code ${code}`); }); ``` 如果希望启动的是外部应用程序,则可以选择使用 `spawn()` 或者更简洁的 `execFile()` 函数。这些方法允许指定要执行的具体命令及其参数,并能够捕获输出流以便进一步处理。 另外值得注意的是,当涉及到网络服务器这样的长期运行服务时,可以直接引入像 Express 这样的框架,并将其绑定至特定端口上监听请求。不过需要注意确保该服务不会干扰到 Electron 自身的工作流程[^1]。 为了使服务能够在应用关闭后继续工作,可能还需要考虑将此服务注册为操作系统级别的守护进程或者是 Windows 上的服务形式存在。这取决于具体的应用场景需求以及平台特性。 #### 关键点总结 - 主要逻辑位于主进程中实施。 - 利用 `child_process` 来管理额外的后台任务和服务。 - 对于复杂的Web服务可集成第三方库如Express等。 - 考虑持久化方案让服务脱离Electron生命周期而存活。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

问白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值