我使用child_process
向控制台写入命令,然后订阅'data'
事件以从中获取输出。问题是有时输出会相互合并。
let command = spawn('vlc', { shell: true });
writeCommand(cmd, callback) {
process.stdin.write(`${cmd}n`);
this.isBusy = true;
this.process.stdout.on('data', (d) => {
callback(d);
});
}
函数writeCommand
在多个地方使用,如何延迟它的执行,直到上一个命令的输出完成?
我的输出可能看起来像(例如status
命令(:
(音量:230((状态停止(>
data
事件没有任何保证,即整个"单位"的输出将汇集在一个data
事件中。它可以很容易地分解为多个data
事件。因此,这与您提供的多个输入生成多个输出的事实相结合,意味着您需要一种方法来解析当您有一个完整的输出集时(因此应该用它调用回调(,以及如何划定输出集之间的边界。
你没有向我们展示你的输出是什么样子的,所以我们不能提供任何关于如何以这种方式解析它的具体建议,但常见的分隔符是类似的东西的双线提要。这将完全取决于您的输出在最后自然地做什么,或者如果您控制子进程创建的内容,您可以在输出的末尾插入什么。
合并输出的另一个解决方案是在第一个命令完成之前不发送第二个命令(可能是使用某种挂起的队列(。但是,您仍然需要一种解析输出的方法,以便知道何时真正完成了上一个输出。
另一个问题:
在显示的代码中,每次调用writeCommand()
时,都会为data
事件添加另一个侦听器。因此,当您调用它两次以发送不同的命令时,现在将有两个侦听器都在侦听同一个data
,并且您将处理同一响应两次而不是一次。
let command = spawn('vlc', { shell: true });
writeCommand(cmd, callback) {
process.stdin.write(`${cmd}n`);
this.isBusy = true;
// every time writeCommand is called, it adds yet another listener
this.process.stdout.on('data', (d) => {
callback(d);
});
}
如果你真的打算多次调用它,并且多个命令可能同时"在飞行",那么你真的不能使用这种编码结构。对于此函数之外的data
事件,您可能需要一个永久侦听器,因为您不希望同时有多个侦听器,而且由于您已经发现来自两个命令的数据可以合并,即使您将它们分开,也无法使用此结构为合并输出的第二部分适当地捕获数据。
您可以使用排队机制在第一个命令完成后执行下一个命令。你也可以使用类似的库https://www.npmjs.com/package/p-limit为你做这件事。