2016-04-05 13 views
8

Ben şu kod:Neden setTimeout çıkışları numaraları değil eklendi

function wait(ms) { 
    var start = +(new Date()); 
    while (new Date() - start < ms); 
} 

(function() { 
    setTimeout(function(){console.log(2)}, 1000); 
    setTimeout(function(){console.log(3)}, 0); 
    setTimeout(function(){console.log(4)}, 0); 
    wait(2000); //!!! blocking events processing here 
})(); 

O çıkarır:

3 
4 
2 

Sonra zaman setTimeoutevent queue fonksiyonu ekler olduğunu okumuştum ve ettik Bu işlev zincirdeki ilkdir, belirtilen sürenin geçip geçmediğini kontrol eder, değilse, yürütmeyi erteler. Bu mantık altında yukarıdaki kodun çıkmasını bekledim: wait() işlevi, wait() işlevinin, olay zincirleme işlemini engellediğinden ve bir çağrı yığını tamamlandığında ve bir tarayıcıda, setTimeout aracılığıyla eklenen işlevleri işlemek için zamana sahip olduğundan, üç işlev de, eklenen ve eklenen sıraya yerleştirilir. 1000, ilk işlev için halihazırda geçti, böylece bir tarayıcı onu alabilir ve çalıştırabilir, ancak ikinci ve üçüncü eklenen işlevleri bekler. Niye ya? Mantığımdaki hata nerede?

+4

tek şey 'setTimeout' garantileri geri aramaları * olarak azından gelecekte kaç milisaniye * istendiği gibi çalıştırılacaktır olmasıdır. Kimse belli bir emri garanti etmeyecek bir şey demedi. – deceze

cevap

9

Geri arama işlevi, zaman aşımı süresi sonrasında sıraya girer. Yani,

setTimeout(function(){console.log(3)}, 0); 
setTimeout(function(){console.log(4)}, 0); 

hemen girer, ancak

setTimeout(function(){console.log(2)}, 1000); 

1 saniye sonra kuyruğu girer. Dolayısıyla sipariş MDN itibaren 3,4,2

:

setTimeout ikinci argüman olarak aktarılan zaman sonra kuyruğa bir mesaj katacak çağrılıyor. Kuyrukta başka bir mesaj yoksa, mesaj hemen işlenir; Ancak, eğer mesajlar varsa, setTimeout mesajı diğer mesajların işlenmesini beklemek zorunda kalacaktır. Bu sebepten dolayı ikinci argüman minimum süreyi gösterir ve garantili bir zaman değildir.

(vurgu mayın)