是否可以在也具有 IPC 挂钩的 node.js 文件中导出 class?

Is it possible to export a class in a node.js file that also has IPC hooks?

[Node.js v8.10.0]

为了清楚起见,我大大简化了这个例子。我有 3 个脚本:parent.js、first.js 和 second.js

parent.js:

'use strict';

const path = require('path');
const {fork} = require('child_process');

const firstScript = path.resolve('first.js');
const first = fork(firstScript);

const secondScript = path.resolve('second.js');
const second = fork(secondScript);

first.on('message', message => {
  console.log('parent received message from first: ' + message);
  second.send(message);
});

second.on('message', message => {
  console.log('parent received message from second: ' + message);
});

first.send('original message');

first.js:

'use strict';

class First {
}

process.on('message', async (message) => {
  console.log('first received message: ' + message);
  process.send(message);
});

module.exports = {First};

second.js:

'use strict';

const {First} = require('./first.js');

process.on('message', message => {
  console.log('second received message: ' + message);
  process.send(message);
});

预期输出:

first received message: original message

parent received message from first: original message

second received message: original message

parent received message from second: original message

实际输出:

first received message: original message

parent received message first: original message

first received message: original message

second received message: original message

parent received message from second: original message

parent received message from second: original message

在这个例子中,第一个class是没有意义的。但它说明了我试图避免的问题。具体来说,second.js 中的 const {First} = require('./first.js'); 行对 IPC 造成严重破坏(如实际输出所示,与预期输出相比)。

目前,我 "solving" 通过将第一个 class 移动到一个单独的文件来解决这个问题。但我想知道是否可以将所有内容保存在一个文件中(即,仍然可以在 first.js 中导出 class —— 但不会造成与 IPC 相关的混乱)。

问题是,当您 require 一个脚本时,在幕后,脚本是 运行 并且在最后提取导出。你所看到的完全符合逻辑 - 当你 运行 $ node parent.js

时基本上有四个过程而不是一个
  1. 父项,由 $ node parent.js
  2. 创建
  3. 首先,由 fork(firstScript)
  4. 创建
  5. 其次,由 fork(secondScript)
  6. 创建
  7. 另一个第一,由require('./first.js')
  8. 创建

如果您需要我添加一个显示消息交换和进程创建的 ascii 艺术进程树,请告诉我,或者如果可以的话!

Ah, that makes sense! But... how can I export a file without executing the parts of the script that create IPC hooks?

JavaScript(节点或网络)中的一种常见设计模式是 只有一个文件静音 。也就是说,所有的文件都只有importing/exporting类和常量,但是只有一个主文件通过引用其他地方的所有智能来实际触发整个程序在源代码中。基本上是这样的:

// hello.js
module.exports = () => console.log('hello world');
// main.js
const hello = require('./hello');
hello();

最好将您的代码分解为这样以简化您的工作,但如果不能,您始终可以根据脚本是否为 来阻止某些代码为 运行 requiredcalled,如 here 所述。在你的例子中,重写 first.js 如下:

'use strict';

class First {
}

// called only if invoked as script
if (require.main==module) {
  process.on('message', async (message) => {
    console.log('first received message: ' + message);
    process.send(message);
  });
}

module.exports = {First};

给出您在 运行ning node parent.js.

时描述的预期输出