SetTimeout, Node.JS'de nasıl çalışır?


112

Sanırım bir kez çalıştırıldığında kuyrukta, ancak kuyrukta tam olarak X milisaniyeden sonra devreye gireceğine dair herhangi bir garanti var mı? Yoksa kuyruktaki diğer ağır görevler geciktirir mi?


14
Hiçbir gerçek zamanlı olmayan işletim sistemi, ciddi bir doğruluk garantisinin olmasını asla mümkün kılmayacaktır. Sistemdeki her türlü şey zamanlayıcı mekanizmasının önüne geçebilir (ve girecektir).
Sivri

Yanıtlar:


174

SetTimeout'un semantiği, bir web tarayıcısındaki ile kabaca aynıdır: zaman aşımı argümanı, bir garanti değil, çalıştırmadan önce beklenecek minimum ms sayısıdır. Ayrıca, sayı olmayan veya negatif bir sayı olan 0'ı geçmek, minimum sayıda ms beklemesine neden olur. Düğümde bu 1 ms'dir, ancak tarayıcılarda 50 ms'ye kadar çıkabilir.

Bunun nedeni, JavaScript tarafından JavaScript'in önceden belirlenmiş olmamasıdır. Şu örneği düşünün:

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

Buradaki akış:

  1. 100 ms için zaman aşımı planlayın.
  2. 5000 ms için meşgul bekleme.
  3. olay döngüsüne geri dönün. bekleyen zamanlayıcıları kontrol edin ve çalıştırın.

Eğer durum bu değilse, o zaman bir bit JavaScript diğerini "kesintiye uğratabilir". Böyle bir kodun akıl yürütmesinin son derece zor olmasını önlemek için muteksler ve semaforlar kurmamız gerekir:

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

Node'un JavaScript yürütmesinin tek iş parçacıklı olması, diğer eşzamanlılık stillerinin çoğundan çok daha kolay çalışılmasını sağlar. Elbette, değiş tokuş, programın kötü davranan bir bölümünün her şeyi sonsuz bir döngü ile engellemesinin mümkün olmasıdır.

Bu, savaşmanın karmaşıklığından daha iyi bir şeytan mı? Bu bağlıdır.


20
Son derece doğru console.logmesaj için +1 alırsınız.
Fund Monica'nın Davası

Dizinizde büyük harfli TIME şeklini beğeniyorum. Çok iyi bir açıklama !!!
Alisson

43

Engellememe fikri, döngü yinelemelerinin hızlı olmasıdır. Bu nedenle, her işaret için yineleme yapmak, setTimeout'un makul bir kesinlik dahilinde doğru olacağı kadar kısa bir süre almalıdır (kapalı belki <100 ms kadar).

Teorik olarak haklı olmanıza rağmen. Bir uygulama yazarsam ve onay işaretini engellersem, setTimeout'lar gecikecektir. Öyleyse sorunuzu cevaplamak için, setTimeout'ların zamanında çalışmasını kim temin edebilir? Siz, engelleyici olmayan kod yazarak, neredeyse her türlü makul doğruluk derecesine kadar doğruluk derecesini kontrol edebilirsiniz.

JavaScript kod yürütme açısından "tek iş parçacıklı" olduğu sürece (web çalışanları ve benzerleri hariç), bu her zaman olacaktır. Tek iş parçacıklı yapı çoğu durumda büyük bir basitleştirmedir, ancak engellemeyen deyimin başarılı olmasını gerektirir.

Bu kodu tarayıcınızda veya düğümde deneyin ve doğruluk garantisinin olmadığını göreceksiniz, aksine setTimeout çok geç olacak:

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){}

Tercüman döngüyü optimize etmedikçe (kromda yapmaz), binler içinde bir şey elde edersiniz. Halkayı çıkarın ve burnunuzda 500 olduğunu göreceksiniz ...


9

Kodun yürütüldüğünden emin olmanın tek yolu, setTimeout mantığınızı farklı bir işleme yerleştirmektir.

Mantığınızı gerçekleştiren ve bir tür akış (belki tcp) aracılığıyla bu işleme veri ileten yeni bir node.js programı oluşturmak için çocuk süreç modülünü kullanın.

Bu şekilde, ana sürecinizde bazı uzun engelleme kodu çalışıyor olsa bile, çocuk işleminiz zaten kendi kendine başlamış ve yeni bir işlem ve yeni bir iş parçacığına bir setTimeout yerleştirmiştir ve böylece beklediğinizde çalışacaktır.

Daha fazla karmaşıklık, daha fazla iş parçacığının çalıştığı ve ardından işlemlerin olduğu bir donanım düzeyindedir ve bu nedenle bağlam değiştirme, beklenen zamanlamada (çok küçük) gecikmelere neden olur. Bu önemsiz olmalı ve önemliyse, ne yapmaya çalıştığınızı, neden bu kadar doğruluğa ihtiyacınız olduğunu ve bunun yerine işi yapmak için ne tür gerçek zamanlı alternatif donanımların mevcut olduğunu ciddi olarak düşünmeniz gerekir.

Genel olarak, alt süreçleri kullanmak ve birden çok düğüm uygulamasını ayrı işlemler olarak bir yük dengeleyici veya paylaşılan veri depolama (redis gibi) ile birlikte çalıştırmak kodunuzu ölçeklendirmek için önemlidir.


9

setTimeoutbir tür iş parçacığıdır , belirli bir süre için bir işlemi tutar ve yürütür.

setTimeout(function,time_in_mills);

burada ilk bağımsız değişken bir işlev türü olmalıdır; örnek olarak isminizi 3 saniye sonra yazdırmak istiyorsanız, kodunuz aşağıdaki gibi olmalıdır.

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

Hatırlanması gereken anahtar nokta, setTimeoutyöntemi kullanarak yapmak istediğiniz her şeyi bir işlevin içinde yapmaktır . Bazı parametreleri ayrıştırarak başka bir yöntemi çağırmak istiyorsanız, kodunuz aşağıdaki gibi görünmelidir:

setTimeout(function(){yourOtherMethod(parameter);},3000);

8

setTimeout(callback,t)en az t milisaniye sonra geri aramayı çalıştırmak için kullanılır . Gerçek gecikme, işletim sistemi zamanlayıcı ayrıntı düzeyi ve sistem yükü gibi birçok harici faktöre bağlıdır.

Bu nedenle, ayarlanan süreden biraz sonra çağrılma olasılığı vardır, ancak daha önce asla çağrılmayacaktır.

Bir zamanlayıcı 24,8 günden fazla olamaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.