itu console.log node.js asynchronous?

95

Apakah console.log/debug/warn/errordi node.js asynchrounous? Maksud saya, apakah eksekusi kode javascript akan berhenti sampai barang dicetak di layar atau akan dicetak di tahap selanjutnya?

Juga, saya tertarik untuk mengetahui apakah mungkin untuk console.log TIDAK menampilkan apa pun jika pernyataan segera setelah itu crash node.

dhruvbird.dll
sumber

Jawaban:

102

Pembaruan: Dimulai dengan Node 0.6, posting ini sudah usang, karena stdout sudah sinkron sekarang.

Baiklah, mari kita lihat apa yang console.logsebenarnya dilakukannya.

Pertama-tama itu adalah bagian dari modul konsol :

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

Jadi itu hanya melakukan beberapa pemformatan dan penulisan ke process.stdout, sejauh ini tidak ada yang asinkron.

process.stdoutadalah pengambil yang didefinisikan pada startup yang diinisialisasi dengan malas, saya telah menambahkan beberapa komentar untuk menjelaskan hal-hal:

.... 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;
});

Dalam kasus TTY dan UNIX kami berakhir di sini , hal ini mewarisi dari soket. Jadi semua yang dilakukan node itu pada dasarnya adalah mendorong data ke soket, lalu terminal akan mengurus sisanya.

Mari kita uji!

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);

Hasil

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

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

Terminal membutuhkan sekitar 1 detik untuk mencetak konten soket, tetapi node hanya membutuhkan 17 milidetik untuk mendorong data ke terminal.

Hal yang sama berlaku untuk kasus aliran, dan juga kasus file ditangani secara asinkron .

Jadi ya, Node.js memegang teguh janji non-pemblokirannya.

Ivo Wetzel
sumber
2
Pembaruan: stdout di node.js sekarang sinkron: groups.google.com/group/nodejs/browse_thread/thread/…
dhruvbird
1
Saya pikir ini sudah usang sekarang: github.com/nodejs/node/issues/3524#issuecomment-151097761
tforgione
@IvoWetzel Saya harus downvote ini sekarang karena sudah usang.
Evan Carroll
Saya tahu ini sudah usang dan segalanya, tetapi Anda mengatakan "tidak ada yang tidak sinkron sejauh ini" segera setelah di process.stdout.write()mana write()menurut definisi asynchronous ...
binki
27

console.warn () dan console.error () memblokir. Mereka tidak kembali sampai panggilan sistem yang mendasarinya berhasil.

Ya, mungkin saja program keluar sebelum semua yang ditulis ke stdout dihapus. process.exit () akan segera menghentikan node, meskipun masih ada antrian penulisan ke stdout. Anda harus menggunakan console.warn untuk menghindari perilaku ini.

Matt Ranney
sumber
1
Ini tidak berlaku untuk Node 0.10.25 di Windows. console.warn()dan console.error()memiliki perilaku non-pemblokiran yang sama dari console.log(). Bahkan ada paket untuk menyelesaikan masalah di Windows .
Lucio Paiva
12

Kesimpulan saya, setelah membaca Node.js 10. * docs (Terlampir di bawah). adalah bahwa Anda dapat menggunakan console.log untuk logging, console.log sinkron dan diimplementasikan di tingkat rendah c. Meskipun console.log bersifat sinkronis, itu tidak akan menyebabkan masalah kinerja hanya jika Anda tidak mencatat data dalam jumlah besar.

(Contoh baris perintah di bawah ini menunjukkan, console.log async dan console.error adalah sinkronisasi )

Berdasarkan Node.js Doc's

Fungsi konsol sinkron ketika tujuannya adalah terminal atau file (untuk menghindari pesan yang hilang jika keluar prematur) dan asinkron ketika itu adalah pipa (untuk menghindari pemblokiran dalam jangka waktu yang lama).

Artinya, dalam contoh berikut, stdout tidak memblokir sementara stderr memblokir:

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

Dalam penggunaan sehari-hari, dikotomi pemblokiran / non-pemblokiran bukanlah sesuatu yang harus Anda khawatirkan kecuali jika Anda> mencatat data dalam jumlah besar.

Semoga membantu

doron aviguy
sumber
Apa yang dimaksud dengan "data dalam jumlah besar"? Apakah itu ditentukan oleh jumlah panggilan ke console.log atau jumlah total yang ditulis? Berapa besar 1KB / ms, 1MB / ms, 1GB / ms?
MattG
3

Console.log adalah asynchronous di windows sementara itu sinkron di linux / mac. Untuk membuat console.log sinkron di windows, tulis baris ini di awal kode Anda mungkin di file index.js. Semua console.log setelah pernyataan ini akan dianggap sinkron oleh interpreter.

if (process.stdout._handle) process.stdout._handle.setBlocking(true);
Ali Azlan
sumber
Ngomong-ngomong, Linux bukan hanya ubuntu.
ozanmuyes
Terima kasih, maafkan komentar kasar saya tetapi Debian adalah titik lemah saya dan tampaknya semua orang yang mulai menggunakan Linux saat ini berpikir Ubuntu adalah Linux (kecuali Anda, saya tahu Anda bukan salah satunya). Semoga harimu menyenangkan :)
ozanmuyes