【问题标题】:Spawn a child process in Electron在 Electron 中生成子进程
【发布时间】:2016-11-05 10:52:59
【问题描述】:

我正在使用 Node v6.2.2 和 Electron v1.2.5。

我有一个基于 Electron 构建的小型应用程序,现在我需要 fork 该进程在另一个节点进程中运行一些长时间运行的任务,但它似乎不起作用,当我查看ChildProcess 对象,我可以看到在参数spawnargs[0] 中是用电子可执行文件而不是节点初始化的,所以我所做的是我尝试使用spawn,但就我而言它不起作用可以说。

这是我用于spawn 进程的代码(在文件./modules/tester.js 中存在):

const {spawn} = require('child_process');

var child = spawn("node", ["worker.js"], { stdio: ['inherit', 'inherit', 'inherit', 'ipc'] });

const self = {};

self.start = () => {
    console.log("start");
    child.send("ping");
};

这是我用于 worker.js 文件的代码:

process.on("message", (data) => {
    console.log(data);
    console.log("pong");
});

最后这就是我的消费方式。

const {app} = require("electron");

const tester = require("./modules/tester");

app.on("ready", () => {
    tester.start();
});

也许我做错了,但我不这么认为,因为当我使用 nodejs 时,它似乎工作得很好。

我尝试了很多示例,但似乎没有一个有效,另一种可能性是我需要在 Electron 中做一些特殊的事情才能使其工作,但我不知道。

【问题讨论】:

  • 从技术上讲,您已经有两个带有 Main 和 Renderer 的进程。在Main进程上运行是不是太多了?
  • @Josh 是的,是的,因为我正在运行 dns 查找并且我需要快速完成,但我有一个解决方案,我所做的是在运行应用程序时我还在外部启动了一个新的 NodeJS 实例,并让 NodeJS 和 Electron 通过 IPC 进行通信。
  • 如何获取电子下那个child_process的输出?

标签: electron


【解决方案1】:

终于解决了。

我解决这个问题的方法正好相反,NodeJS 在生产机器上可用,所以我只写了一个start.js 脚本,它基本上产生了一个子进程来运行 Electron,而在父进程上我运行了这么长时间运行任务,最后我使用 IPC 在两个进程之间进行通信。

【讨论】:

  • 您是否还在使用这种“预分叉”方法,或者您是否曾经让 spawn 工作?
  • @Fraser 好吧,我不再从事这个项目,所以我没有改变它。 :)
【解决方案2】:

如果您使用 --asar 标志编译 Electron,based on the docs 将是一个问题。

还有this issue 不能将stdio 附加到父级。因此,假设分离的 stdio 不会破坏交易,您可以尝试{ stdio: 'ignore' }。

【讨论】:

    【解决方案3】:

    另外,你可以在 electron 进程中 fork nodejs 文件:

    let serverProc = require('child_process').fork(
      require.resolve('./server.js'),
      ['--key', 'value'], // pass to process.argv into child
      {
        // options
      }
    )
    serverProc.on('exit', (code, sig) => {
      // finishing
    })
    serverProc.on('error', (error) => {
      // error handling
    })
    

    【讨论】:

      【解决方案4】:

      如果它是便携式 .exe,此答案将适合您的应用程序。我自己没有使用过可安装的,所以对此不太了解。

      在进行开发的同时创建一个子进程真的很容易。最简单的是使用 Node 的 child_process 中的 fork()(尽管我们可以根据需要使用任何 spawn/exec/execFile... 等)。

      当我们将应用程序打包为一个可执行文件时,困难的部分就出现了,其中包含打包的文件为“app.asar”。

      关键是,你了解“app.asar”是什么吗? “app.asar” 乍一看看起来像一个普通的捆绑文件,但它实际上是一个虚拟目录,这意味着你可以像在任何其他目录中一样遍历它,也许只是考虑一下作为目录名。如果您在电子代码的主进程下执行__dirname,您会看到位置为 '/path/to/app.asar'。

      您如何看到“app.asar”中的内容? - reference

      fs.readdirSync('/path/to/app.asar')
      

      回答

      您需要将文件(将在单独的进程上运行的文件,例如文件名:“child.process.js”)单独捆绑/复制到您的打包程序(如:electron-builder)所在的文件夹中创建EXE。假设您将所有内容打包在一个“dist”文件夹下,那么这个 dist 文件夹应该有文件 child.process.js。现在这个“dist”文件夹本身将变成“app.asar”。

      当您为fork() 指定child.process.js 的路径时,如果文件“child.process.js”直接位于dist 中,则如下所示:

      fork(path.join(__dirname, 'child.process.js'))
      

      如果它存在于子目录下,则给出适当的路径。

      有趣的是,上面的代码在将其用作可移植 EXE 和开发时都有效(如果您将所有主要流程文件捆绑到一个文件中。)



      我花了 3 天时间才弄清楚这一点。在测试 EXE 时我是如何进行调试的?我使用fs 写入文件,然后打开它们并读取它们的内容。当我打印fs.readdirSync('/path/to/app.asar')的输出时,我才意识到解决方案。有趣的是我有两个 dist 文件夹,我正在打包我的子文件以用于本地开发 dist,但没有为我打包应用程序的 dist 执行此操作。

      希望这对某人有所帮助!

      【讨论】:

        猜你喜欢
        • 2017-11-08
        • 1970-01-01
        • 1970-01-01
        • 2016-02-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-02
        • 2017-03-25
        相关资源
        最近更新 更多