Как показать проценты сделанные в терминале

Добрый день всем.

Сегодня я работаю над этим сложным сценарием, который делает запрос к сайту с рендерингом на стороне сервера, получает HTML, разбивает и собирает некоторые данные. Скрипт имеет 4 фазы: phaseOne, phaseTwo, phaseThree и phaseFour.

Какие фазы имеют похожий интерфейс:

class PhaseOne {
  constructor(MAP) {
    this.MAP = MAP || MAP;
  }

  // All code related with the phase here.
  process() {}
}

Итак, я работаю над этим объектом MAP на всех фазах, и я вызываю каждую фазу в стеке, например так:

let phases = require('./phases');

[
  // 'Initial',
  'PhaseOne',
  'PhaseTwo',
  'PhaseThree',
  'PhaseFour',
].reduce((m, fn) => {
  return new phases[fn](m).process();
}, MAP);

Все работает нормально. Моя проблема в том, что некоторые фазы ДЕЙСТВИТЕЛЬНО медленны... вся программа займет 30 минут, чтобы закончить... и я хотел бы видеть в моем терминале процент каждой фазы.

Подобно:

PhaseOne: 10%
PhaseOne: 11%
PhaseOne: 12%

Но я понятия не имею, и я не могу найти хороший учебник, чтобы сделать это..

В настоящее время внутри моих функций процесса у меня есть для циклов, если операторы.. в общем, я использую императивный стиль..

Пример PhaseOne:

   // In this phase we need the property string in MAP.aguia01 to
    // assign the first context and extract the data with regex.
    if (typeof this.MAP.aguia01.string === 'undefined') {
      cli.fatal(
        'MAP doesn\'t have the necessary properties to run in Aguia01 phase. Exiting...'
      );
    }

    for (let month of months) {
      this.MAP.aguia01.string += requests.aguia01.apply(this, [month]);
    }

    for (let info of patterns.aguia01.infos) {
      this.MAP.aguia01.infos[info.name] = (
        this.MAP.aguia01.string.match(info.pattern)
      )[1];
    }

    for (let line of patterns.aguia01.lines) {
      this.MAP.aguia01.lines[line.name] = (
        this.MAP.aguia01.string.match(line.pattern)
      )[1];
    }

Итак... Можно ли делать то, что я хочу с императивным стилем?

Благодарю.

2 ответа

Существует пакет прогресса, но только от вас зависит, как вы определяете "прогресс". Вы определяете количество тиков, соответствующих завершенному состоянию, а затем просто вызываете метод на индикаторе выполнения, чтобы сделать его "прогрессом". Пример:

var ProgressBar = require('progress');

// 10 ticks to complete the task
var bar = new ProgressBar(':bar', { total: 10 });
var timer = setInterval(function () {
  // make the bar tick(), each call will make a 10% progress
  bar.tick();
  if (bar.complete) {
    console.log('\ncomplete\n');
    clearInterval(timer);
  }
}, 100);

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

let phases = require('./phases');

//set up
let progressMonitor =  new require('events')
progressMonitor.on('progress', percentDone => {
  console.log(percentDone + '% done')
})

// your existing code
[
  // 'Initial',
  'PhaseOne',
  'PhaseTwo',
  'PhaseThree',
  'PhaseFour',
].reduce((m, fn) => {
  return new phases[fn](m).process(progressMonitor);
}, MAP);

а затем внутри ваших функций процесса:

class PhaseOne {
 constructor(MAP) {
    this.MAP = MAP || MAP;
  }

  // All code related with the phase here.
  process(progressMonitor) {
    //do work
    progressMonitor.emit('progress', 10)
    //more work
    progressMonitor.emit('progress', 15)
    //much work
    progressMonitor.emit('progress', 75)
  }
}
Другие вопросы по тегам