如何延迟函数调用直到它的回调在其他地方完成

How to delay function call until its callback will be finished in other places

我正在使用 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)(状态停止)>

您可以使用排队机制,在第一个命令完成后执行下一个命令。您也可以使用像 https://www.npmjs.com/package/p-limit 这样的库来为您完成。

data 流上的事件对整个 "unit" 输出将在单个 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);
  });
}

如果你真的打算多次调用这个并且多个命令可以同时"in flight",那么你真的不能使用这种编码结构。对于此函数之外的 data 事件,您可能需要一个永久监听器,因为您不想同时拥有多个监听器,而且您已经发现来自两个命令的数据可以合并,即使将它们分开,也不能使用此结构为合并输出的第二部分适当地捕获数据。