Проблемы с записью данных журнала с Node.JS Ввод-вывод

#node.js

#node.js

Вопрос:

Я подключаюсь к узлу.JS с библиотекой, которая обеспечивает доступ к данным в стиле итератора:

 next = log.get_next()
  

Я фактически хочу написать следующее:

 while (next = log.get_next()) {
    console.log(next);
}
  

и перенаправление stdout в файл (например node log.js > log.txt ). Это хорошо работает для небольших журналов, но для больших партий выходной файл пуст, и использование моей памяти зашкаливает.

Похоже, я не до конца понимаю ввод-вывод в node, поскольку простой бесконечный цикл, который записывает строку на консоль, также демонстрирует такое же поведение.

Было бы здорово дать несколько советов о том, как выполнить эту задачу. Спасибо.

Ответ №1:

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

 var os = require('os');

process.stdout.on('drain', function(){
  dump();
});

function dump(){
  for (var i=0; i<10000; i  )
    console.log('xxxx');
  console.error(os.freemem());
}

dump();
  

Если вы запускаете как:

 node testbuffer > output
  

вы увидите, что файл периодически увеличивается, а память достигает устойчивого состояния.

Ответ №2:

Библиотека, с которой вы взаимодействуете, должна принимать обратный вызов. Node.js разработан, чтобы быть неблокирующим. Я думаю, что, возможно, console.log продолжает возвращать управление циклу (и log.get_next() ) перед отправкой выходных данных.

Если модуль был переписан, чтобы заставить get_next поддерживать обратный вызов, улучшенный код может быть таким:

 var log_next = function() {
  console.log(next);
  log.get_next(log_next);
};
log.get_next(log_next);
  

(Существуют библиотеки и шаблоны, которые могли бы сделать этот код красивее.)

Если код только синхронный и должен оставаться таким, какой он есть, вызов setTimeout с 0 или другим небольшим числом может предотвратить блокировку всего процесса.

 var log_next = function() {
  console.log(log.get_next());
  setTimeout(log_next, 0);
};
log_next();