在节点 child_process 事件处理程序之间共享数据的 'right' 方法是什么?

What is the 'right' way to share data between node child_process event handlers?

在节点子进程事件处理程序之间共享数据的正确方法是什么? child-process docs将可用事件定义为'close'、'disconnect'、'error'、'exit'、'message'和'spawn',表示可以为每个定义一个处理程序,并提供一些这样的例子:

process.on('message', (m) => {
  console.log('CHILD got message:', m);
});

subprocess.on('error', (err) => {
  console.error('Failed to start subprocess.');
});

我正在寻找一种在分叉的子进程上的事件处理程序之间共享数据的方法。我已经发现选项对象允许您在生成进程时指定环境变量,如下所示:

const tableInsertionProcess = childProcess.fork(
  './recordInsertion',
  [], // no arguments
  {
    env: {
      tableName: tableName, // add tableName as environment variable to be accessible in all event handlers
      ...process.env        // process.env is the default; include it for consistency
    },
  }
)
log_info(`Spawned child process ${tableInsertionProcess.pid} for ${tableName}`)

tableInsertionProcess.send({
  notes: notes,
  inputCsv: inputCsv
})

有没有办法在事件处理程序之间共享数据?如果您将 process/thread 视为一个对象,这将是对象级数据:私有字段或成员。类似于以下内容:

let messagesReceived = 0;

process.on('message', (m) => {
  console.log('CHILD got message:', m);
  messagesReceived += 1;
});

process.on('error', (err) => {
  console.error(`Error after processing ${messagesReceived} messages: ${err.message}`);
});

有更好的方法或正确的方法吗?全局变量感觉不对

你能改变一个处理程序中的环境变量并让它们显示在不同的处理程序中吗? (充其量似乎是一种反模式。)


看起来参数(.fork() 的第二个参数)在使用 subprocess.spawnargs 的每个事件处理程序中都可用。不过,文档中没有这方面的示例。我也想知道,为什么事件处理程序定义为 process.on 而所有其他字段都定义在 subprocess 变量上?


如果 标签放错了,我们深表歉意。标记描述暗示但没有明确说明它适用于 Unix 子进程。 Node 的子进程文档说他们试图像 unix 一样。让我知道,我会删除它。

Is there a better way or right way of doing this?

如果您在谈论从同一个 child_process 中的多个事件处理程序访问公共数据,那么您只需定义模块变量或一些模块级数据结构,两者都可以访问。这里没什么好看的。

您的 messagesReceived 示例可以正常工作。仅此而已。

The global variable feels wrong.

messagesReceived 不是全局的。它是一个模块级变量,这对模块级数据来说是一件非常好的事情。有成千上万的理由想要跟踪模块级数据。如果要在同一进程中跨模块共享该数据结构,则可以导出数据结构的根或导出具有访问数据方法的对象。如果一切都在一个模块中,那么您可以直接访问模块级数据或对象。

Can you alter the environment variables in one handler and have them show up in a different handler? (Seems like an anti-pattern at best.)

当在模块范围内声明的常规 Javascript 变量工作正常时,真的没有理由将这样的东西放在环境变量中。修改常规 Javascript 变量并使用它们进行编程比尝试在进程环境中存储可修改的数据要容易得多。

I'm also wondering, why is the event handler defined as process.on but all the other fields are defined on the subprocess variable?

这与您询问的其他问题无关。 process.on('message', (m) => {...} 用于为其他进程或子进程向您的进程发送消息时注册事件处理程序。因此,process 事件是您的流程中发生的事情。

您的进程在不同 subprocesschild_process 上的事件处理程序用于根据与其他进程相关的各种生命周期事件获取事件。这些是其他进程发生的事情(特别是当他们退出时或与他们的 stdiostdin.

相关的事件)

It also looks like the arguments (second parameter to .fork()) are available in every event handler)

.fork() 的第二个参数创建传递给 child_process 的命令行参数,它们将在另一个进程中作为 process.argv (如果它是 nodejs 应用程序)或但是,如果进程是在其他一些编程环境中创建的,则命令行参数可用。