является node.js 'console.log асинхронным?


95

Находятся ли console.log/debug/warn/errorв node.js асинхронно? Я имею в виду, остановится ли выполнение кода javascript до тех пор, пока материал не будет напечатан на экране, или он будет напечатан на более позднем этапе?

Кроме того, мне интересно узнать, возможно ли, чтобы console.log НЕ отображала ничего, если оператор сразу после этого выдает сбой node.

Ответы:


102

Обновление: начиная с Node 0.6 этот пост устарел, так как stdout теперь синхронный .

Что ж, посмотрим, что на console.logсамом деле происходит.

В первую очередь это часть консольного модуля :

exports.log = function() {
  process.stdout.write(format.apply(this, arguments) + '\n');
};

Таким образом, он просто выполняет некоторое форматирование и запись process.stdout, пока ничего асинхронного.

process.stdout- это получатель, определенный при запуске, который лениво инициализируется, я добавил несколько комментариев, чтобы объяснить вещи:

.... code here...
process.__defineGetter__('stdout', function() {
  if (stdout) return stdout;                            // only initialize it once 

  /// many requires here ...

  if (binding.isatty(fd)) {                             // a terminal? great!
    stdout = new tty.WriteStream(fd);
  } else if (binding.isStdoutBlocking()) {              // a file?
    stdout = new fs.WriteStream(null, {fd: fd});
  } else {
    stdout = new net.Stream(fd);                        // a stream? 
                                                        // For example: node foo.js > out.txt
    stdout.readable = false;
  }

  return stdout;
});

В случае TTY и UNIX мы попадаем сюда , эта вещь наследуется от сокета. Таким образом, все, что обычно делает этот узел, - это помещать данные в сокет, а все остальное выполняет терминал.

Давай проверим!

var data = '111111111111111111111111111111111111111111111111111';
for(var i = 0, l = 12; i < l; i++) {
    data += data; // warning! gets very large, very quick
}

var start = Date.now();
console.log(data);
console.log('wrote %d bytes in %dms', data.length, Date.now() - start);

Результат

....a lot of ones....1111111111111111
wrote 208896 bytes in 17ms

real    0m0.969s
user    0m0.068s
sys  0m0.012s

Терминалу требуется около 1 секунды, чтобы распечатать содержимое сокетов, но узлу требуется всего 17 миллисекунд, чтобы отправить данные на терминал.

То же самое касается случая потока, а также случай файла получает асинхронную обработку .

Так что да, Node.js выполняет свои обещания о неблокировании.


2
Обновление: stdout в node.js теперь синхронный: groups.google.com/group/nodejs/browse_thread/thread/…
dhruvbird

1
Я думаю, что сейчас это устарело: github.com/nodejs/node/issues/3524#issuecomment-151097761
tforgione

@IvoWetzel Мне придется проголосовать против этого сейчас, поскольку он устарел.
Эван Кэрролл,

Я знаю , что это является устаревшим , и все, но вы говорите «ничего асинхронным до сих пор» сразу после того, как, process.stdout.write()где write(), по определению асинхронного ...
Бинки

27

console.warn () и console.error () блокируются. Они не возвращаются, пока базовые системные вызовы не завершатся успешно.

Да, программа может выйти до того, как все, что записано в stdout, будет сброшено. process.exit () немедленно завершит работу узла, даже если в stdout все еще есть записи в очереди. Вы должны использовать console.warn, чтобы избежать такого поведения.


1
Это не относится к узлу 0.10.25 в Windows. console.warn()и console.error()имеют такое же неблокирующее поведение, что и console.log(). Есть даже пакет для решения проблемы в Windows .
Лучио Пайва

12

Мое заключение после прочтения документов Node.js 10. * (прилагается ниже). заключается в том, что вы можете использовать console.log для ведения журнала, console.log синхронна и реализована на низком уровне c. Хотя console.log является синхронным, он не вызовет проблем с производительностью, только если вы не регистрируете большой объем данных.

(Пример командной строки ниже демонстрирует, console.log async и console.error синхронизируются )

На основе Node.js Doc's

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

То есть в следующем примере stdout не блокирует, а stderr блокирует:

$ node script.js 2> error.log | tee info.log

При повседневном использовании дихотомия блокирующий / неблокирующий - это не то, о чем вам следует беспокоиться, если вы> не регистрируете огромные объемы данных.

Надеюсь, поможет


Что такое «огромный объем данных»? Это определяется количеством обращений к console.log или общей записываемой суммой? Что такое огромные 1 КБ / мс, 1 МБ / мс, 1 ГБ / мс?
MattG

3

Console.log асинхронен в Windows, тогда как в linux / mac он синхронен. Чтобы сделать console.log синхронным в Windows, напишите эту строку в начале вашего кода, вероятно, в файле index.js. Любой console.log после этого оператора будет рассматриваться интерпретатором как синхронный.

if (process.stdout._handle) process.stdout._handle.setBlocking(true);

Кстати, Linux - это не просто Ubuntu.
ozanmuyes

Спасибо, извините за педантичный комментарий, но Debian - мое слабое место, и кажется, что все, кто начал использовать Linux в настоящее время, думают, что Ubuntu - это Linux (кроме вас, я знаю, что вы не один из них). Хорошего дня :)
ozanmuyes
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.