асинхронний node.js 'console.log?


95

Чи є console.log/debug/warn/errorв node.js асинхронний? Я маю на увазі, чи зупиниться виконання коду javascript, поки матеріал не надрукується на екрані, або він надрукується пізніше?

Крім того, мені цікаво дізнатись, чи можливо, щоб console.log НЕ показував нічого, якщо оператор відразу після аварії вузла.

Відповіді:


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()за визначенням асинхронне ...
binki

26

console.warn () та console.error () блокують. Вони не повертаються, доки базові системні виклики не пройшли успішно.

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


1
Це не відповідає Node 0.10.25 у Windows. console.warn()і console.error()мають однакову неблокувальну поведінку console.log(). Існує навіть пакет для вирішення проблеми в Windows .
Lucio Paiva

12

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

(Наведений нижче приклад командного рядка демонструє, console.log async та console.error є синхронізацією )

На основі Node.js Doc

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

Тобто, у наступному прикладі 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 (крім вас, я знаю, що ви не один з них).
Гарного вам
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.