nodejs child_process: написать стандартный вывод в реальном времени и запустить последовательно - PullRequest
0 голосов
/ 27 мая 2018

Инфо
узел: v9.4.0

Я хотел бы запускать внешние команды последовательно, но видеть стандартный вывод в реальном времени.

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

const spawn = require('child_process').spawn;
const fs = require('fs');
let test;

fs.readdirSync('./test/').forEach(file => {
    test = spawn('npm', ['test', 'test/' + file]);

    test.stdout.on('data', (data) => {
        console.log(`${data}`);
    }); 

    test.stderr.on('data', (data) => {
        console.log(`${data}`);
    }); 

    test.on('close', (code) => {
        console.log(`code: ${code}`);
    }); 
});

Не могли бы вы рассказать мне, как выполнить эти две вещи одновременно?
- запускать все тестовые примеры один за другим
- записывать стандартный вывод в режиме реального времени

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

1 Ответ

0 голосов
/ 27 мая 2018

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

class Mutex {
  constructor() {
    this._queue = [];
  }

  lock() {
    return new Promise((resolve, reject) => {
      const allow = () => {
        resolve(this._unlock.bind(this));
      };
      this._queue.push(allow);
      if (this._queue.length === 1) {
        allow();
      }
    });
  }

  _unlock() {
    this._queue.shift();
    const next = this._queue[0];
    if (typeof next === 'function') {
      next();
    }
  }
}

Тогда вашкод становится:

const spawn = require('child_process').spawn;
const fs = require('fs');
let test;

const mutex = new Mutex();

fs.readdirSync('./test/').forEach(async file => {
    const unlock = await mutex.lock();

    test = spawn('npm', ['test', 'test/' + file]);

    test.stdout.on('data', (data) => {
        console.log(`${data}`);
    }); 

    test.stderr.on('data', (data) => {
        console.log(`${data}`);
    }); 

    test.on('close', (code) => {
        unlock();
        console.log(`code: ${code}`);
    }); 
});
...