Ожидание ввода потока от дочернего процесса в Node.js

#javascript #node.js #stream #child-process

Вопрос:

Мой главный Node.js процесс порождает дочерний процесс. Я хочу общаться с дочерним процессом, отправляя ему данные через его stdin и считывая их из его stdout. Дочерний процесс будет продолжен. Я хочу отправить ему сообщение, затем дождаться ответа, что-то сделать с ответом, а затем продолжить основной процесс. Как мне лучше всего это сделать? Я попробовал следующее:

     // I call this function after sending to child's stdin
    private async readWaitStream() {
        let data = '';

        let chunk = '';
        while (chunk = this._child.stdout.read()){
            data  = chunk;
        }

        // doesn't finish because child process stays running
        await finished(this._child.stdout); 
        return data;
    }
 

Дочерний процесс никогда не заканчивается, и это не работает.

Комментарии:

1. Что такое finished ?

2. Возможно, вы захотите попробовать for await (const chunk of this._child.stdout) …

Ответ №1:

Просто прослушайте end событие stdout , а затем верните данные. Тебе нужно обернуть это в Обещание.

   private async readWaitStream() {
    return new Promise((resolve) => {
      let data = '';

      this._child.stdout.on('readable', () => {
        let chunk = '';
        while (chunk = this._child.stdout.read()) {
          data  = chunk;
        }
      });

      this._child.stdout.on('end', () => {
        resolve(data); // return data
      });
    });
  }
 

Комментарии:

1. Хм, мне показалось, что это не сработало. Дочерний процесс не закончился, и обещание не было выполнено.

2. @XSeven Обновил логику. Регистрируйте слушателей одновременно.

3. к сожалению, это тоже не сработало для меня. По-прежнему похоже, что stdout дочернего процесса никогда не выдает «конец». Дочерний процесс должен оставаться запущенным и получать более поздние входные данные. Есть ли способ просто дождаться следующей реакции ребенка? @hoangdv

Ответ №2:

Я придумал, как решить эту проблему. Я использую once.('readable' ... ) , например:

 private readWaitStream() {
    return new Promise(resolve => {
        let data = '';
        this._child.once('readable', () => {
            let chunk = '';
            while (chunk = this._child.read()) {
                data  = chunk;
            }
            resolve(data);
        });
    });
}
 

Когда я then выполняю функцию, мы будем ждать ввода, и обещание разрешится только после того, как будет доступен следующий ввод.