Bagaimana cara kerja setTimeout di Node.JS?

112

Saya rasa setelah dijalankan, itu ada di antrian, tetapi dalam antrian apakah ada jaminan itu akan dipanggil tepat setelah X milidetik? Atau akankah tugas berat lainnya yang lebih tinggi pada antrian akan menunda?

MyCodeGone
sumber
14
Tidak ada sistem operasi non-realtime yang memungkinkan adanya jaminan keakuratan yang serius. Segala macam hal di sistem dapat (dan akan) menghalangi mekanisme pengatur waktu.
Pointy

Jawaban:

174

Semantik setTimeout kurang lebih sama seperti di browser web: argumen batas waktu adalah jumlah minimum md yang harus menunggu sebelum dijalankan, bukan jaminan. Selanjutnya, melewatkan 0, bukan angka, atau angka negatif, akan menyebabkannya menunggu dalam jumlah minimum ms. Di Node, ini adalah 1ms, tetapi di browser bisa mencapai 50ms.

Alasannya adalah karena tidak ada preemption JavaScript oleh JavaScript. Pertimbangkan contoh ini:

setTimeout(function () {
  console.log('boo')
}, 100)
var end = Date.now() + 5000
while (Date.now() < end) ;
console.log('imma let you finish but blocking the event loop is the best bug of all TIME')

Alurnya di sini adalah:

  1. jadwalkan waktu tunggu untuk 100 md.
  2. busywait untuk 5000ms.
  3. kembali ke loop acara. periksa timer yang tertunda dan jalankan.

Jika bukan ini masalahnya, maka Anda dapat memiliki satu bit JavaScript "mengganggu" yang lain. Kita harus menyiapkan mutex dan semaphor dan semacamnya, untuk mencegah kode seperti ini menjadi sangat sulit untuk dipikirkan:

var a = 100;
setTimeout(function () {
  a = 0;
}, 0);
var b = a; // 100 or 0?

Single-threadedness dari eksekusi JavaScript Node membuatnya lebih sederhana untuk digunakan daripada kebanyakan gaya konkurensi lainnya. Tentu saja, trade-off adalah bahwa ada kemungkinan bagian program yang berperilaku buruk memblokir semuanya dengan loop tak terbatas.

Apakah ini iblis yang lebih baik untuk berperang daripada kerumitan preemption? Itu tergantung.

isaacs
sumber
20
Anda mendapatkan +1 untuk console.logpesan yang sangat akurat .
Dana Gugatan Monica
Saya suka bagaimana Anda menggunakan TIME di string Anda. Penjelasan yang sangat bagus !!!
Alisson
43

Gagasan non-pemblokiran adalah bahwa pengulangan iterasi cepat. Jadi, untuk mengulangi setiap centang harus membutuhkan waktu yang cukup singkat sehingga setTimeout akan akurat hingga dalam presisi yang wajar (mungkin mati sekitar <100 ms atau lebih).

Secara teori, Anda benar. Jika saya menulis aplikasi dan memblokir tanda centang, maka setTimeout akan tertunda. Jadi untuk menjawab pertanyaan Anda, siapa yang dapat memastikan setTimeout dijalankan tepat waktu? Anda, dengan menulis kode non-pemblokiran, dapat mengontrol tingkat akurasi hingga hampir semua tingkat akurasi yang wajar.

Selama javascript adalah "single-threaded" dalam hal eksekusi kode (tidak termasuk web-worker dan sejenisnya), itu akan selalu terjadi. Sifat single-threaded adalah penyederhanaan besar dalam banyak kasus, tetapi memerlukan idiom non-blocking agar berhasil.

Coba kode ini di browser atau di node, dan Anda akan melihat bahwa tidak ada jaminan keakuratan, sebaliknya, setTimeout akan sangat terlambat:

var start = Date.now();

// expecting something close to 500
setTimeout(function(){ console.log(Date.now() - start); }, 500);

// fiddle with the number of iterations depending on how quick your machine is
for(var i=0; i<5000000; ++i){}

Kecuali penerjemah mengoptimalkan pengulangan (yang tidak di chrome), Anda akan mendapatkan ribuan. Hapus loop dan Anda akan melihat 500 di hidung ...

davin
sumber
9

Satu-satunya cara untuk memastikan kode dieksekusi adalah dengan menempatkan logika setTimeout Anda dalam proses yang berbeda.

Gunakan modul proses anak untuk menelurkan program node.js baru yang menjalankan logika Anda dan meneruskan data ke proses itu melalui semacam aliran (mungkin tcp).

Dengan cara ini bahkan jika beberapa kode pemblokiran yang lama berjalan dalam proses utama Anda, proses anak Anda telah dimulai sendiri dan menempatkan setTimeout dalam proses baru dan utas baru dan dengan demikian akan berjalan saat Anda mengharapkannya.

Komplikasi lebih lanjut berada pada tingkat perangkat keras di mana Anda memiliki lebih banyak utas yang berjalan kemudian proses dan dengan demikian peralihan konteks akan menyebabkan penundaan (sangat kecil) dari waktu yang Anda harapkan. Ini harus diabaikan dan jika itu penting, Anda perlu mempertimbangkan secara serius apa yang coba Anda lakukan, mengapa Anda memerlukan akurasi seperti itu dan perangkat keras alternatif waktu nyata apa yang tersedia untuk melakukan pekerjaan itu.

Secara umum, menggunakan proses anak dan menjalankan beberapa aplikasi node sebagai proses terpisah bersama dengan penyeimbang beban atau penyimpanan data bersama (seperti redis) penting untuk menskalakan kode Anda.

Raynos
sumber
9

setTimeoutadalah sejenis Thread , ini memegang operasi untuk waktu tertentu dan mengeksekusi.

setTimeout(function,time_in_mills);

di sini argumen pertama harus berupa tipe fungsi; sebagai contoh jika Anda ingin mencetak nama Anda setelah 3 detik, kode Anda harus seperti di bawah ini.

setTimeout(function(){console.log('your name')},3000);

Hal penting yang perlu diingat adalah, apa pun yang ingin Anda lakukan dengan menggunakan setTimeoutmetode ini, lakukan di dalam fungsi . Jika Anda ingin memanggil metode lain dengan mengurai beberapa parameter, kode Anda akan terlihat seperti di bawah ini:

setTimeout(function(){yourOtherMethod(parameter);},3000);
Ashana.Jackol
sumber
8

setTimeout(callback,t)digunakan untuk menjalankan panggilan balik setelah setidaknya t milidetik . Penundaan sebenarnya bergantung pada banyak faktor eksternal seperti perincian timer OS dan beban sistem.

Jadi, ada kemungkinan akan dipanggil sedikit setelah waktu yang ditentukan, tapi tidak akan pernah dipanggil sebelumnya.

Pengatur waktu tidak dapat menjangkau lebih dari 24,8 hari.

Siva Prakash
sumber