Обновление: Начиная с узла 0.6, этот пост устарел, так как стандартный вывод синхронен сейчас.
Хорошо, давайте посмотрим, что на самом деле делает console.log
. 1008 *
Прежде всего, это часть консольного модуля :
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 остается верным своим неблокирующим обещаниям.