Как отложить вызов функции до ее завершения в других местах - PullRequest
0 голосов
/ 17 марта 2020

Я использую 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) (состояние остановлено)>

Ответы [ 2 ]

1 голос
/ 17 марта 2020

data события в потоке имеют ноль, гарантирующее, что вся «единица» вывода соберется в одно data событие. Он может быть легко разбит на несколько data событий. Таким образом, это в сочетании с тем фактом, что вы предоставляете несколько входов, которые генерируют несколько выходов, означает, что вам нужен способ анализа, когда у вас есть полный набор выходных данных, и, таким образом, следует вызывать обратный вызов с ним, а также как определить границы между наборы выходных данных.

Вы не показываете, как выглядит ваш вывод, поэтому мы не можем предложить никаких конкретных предложений о том, как его анализировать таким образом, но общие разделители - это двойные переводы строк подобных вещей. , Это будет полностью зависеть от того, что ваш вывод естественным образом делает в конце или если вы контролируете контент, который создает дочерний процесс, что вы можете вставить в конец вывода.

Другой обходной путь для объединенного вывода будет не отправлять 2-ю команду до тех пор, пока не будет выполнена 1-я (возможно, с использованием какой-либо очереди ожидания). Но вам все равно понадобится способ синтаксического анализа выходных данных, чтобы узнать, когда на самом деле вы завершили предыдущий вывод.

Другая проблема:

В показанном вами коде при каждом вызове 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, который находится за пределами этой функции, потому что вы не хотите иметь более одного прослушивателя одновременно и поскольку вы уже обнаружили, что данные двух команд можно объединить , даже если вы разделите их, вы не сможете использовать эту структуру для надлежащего сбора данных для второй части объединенного вывода.

1 голос
/ 17 марта 2020

Вы можете использовать механизм очередей для выполнения следующей команды после завершения первой. Вы также можете использовать библиотеку типа https://www.npmjs.com/package/p-limit, чтобы сделать это за вас.

...