2012-03-19 28 views
20

Her zaman, JavaScript'in tek iş parçacıklı olduğundan, kod yürütmenin ortasındayken işleyicilerin çalıştırılmasından endişelenmeden olay işleyicileri ekleyebileceğimi düşündüm. Benim için sürpriz olabilirdi. this answer,'a göre 'Yanıt Vermeyen Komut Dosyası' iletişim kutusu, betik hala devam ederken olayların yükseltilmesine neden olabilir.JavaScript akışı akışı kesintiye uğrayabilir mi?

Aşağıdaki kod ile bu test:

<script> 
    function loop() { 
     var cond; 
     onblur = function (event) { 
      cond = false; 
     }; 
     cond = true; 
     while (cond) 
      ; 
     alert('loop exited!'); 
    } 
</script> 
<button onclick="loop()">loop()</button> 

(jsFiddle)

Firefox 11.0, işlev baskılar devam tıkladıktan sonra "döngüden çıkılır". Döngü, yürütmeye izin verilen olaylar ile duraklatılmış gibi görünüyor. Bu, hedef iş parçacığının içeriğini geçici olarak değiştiren Unix signal,'a benzer. Fakat dış devletin değiştirilmesine izin verdiği için çok daha tehlikelidir.

Bu bir hata mı? Artık, JavaScript'in tek akış yürütme modeline bağlı olmamalı ve tüm komut dosyalarının yeniden giriş yapmamasını sağlamalı mıyım? Yoksa bunun olmasına izin veren büyük bir tarayıcıya rağmen takip etmeye değmez bir kusur mu?

+2

Sanırım asıl soru şu olurdu: "standart ne için çağrı yapıyor". –

+1

Bazı yerleşik davranışlarla ("alert()" vb.) Gerçekleşen "duraklama" nın, o anda çalışan işlevden "getiri" zorlayan yorumlayıcı biçimini aldığını düşünmek daha iyi olur. "duraklama" bittiğinde, yürütmeye devam edilir.Diğer bir ifadeyle, "duraklama" devam ederken fonksiyonun gerçekte geri döndüğünü düşünmek ve devam etmek için devam edilmeye devam edilir. Bu şekilde, olay işleme, olağan olay işleme gibi olduğu için çok daha anlamlı olur. – Pointy

+7

Bir "yanıt vermiyor" komut istemi, tasarlamanız gereken normal bir şey değildir. Uygulamanız bozulduğunda kullanıcı bu diyaloglardan birini alır. Komut dosyanızı, "yanıtsız komut dosyası" isteminin gerçekleşmemesi için tasarlamalısınız ve daha sonra yeniden giriş hakkında endişelenmenize gerek kalmayacak. Bana bu komut isteminde büyük bir tarayıcının olaylara izin vermesine izin veren küçük bir hata olduğu görünmüyor, ancak kodunuzu düzeltmek için çok daha önemli olduğunu düşünüyorum, bu yüzden istem hiç oluşmaz ve bu asla bir sorun değildir. – jfriend00

cevap

2

Yani, sonsuz bir döngü oluşturursanız, JavaScript'inizi asacaktır. Diff tarayıcıları bunu farklı şekilde ele alacaktır. Firefox 11 benim için senaryonun asılı olduğunu söyleyen bir pencere açıyor. Chrome şu anda benim için dönüyor.

Bu, noktayı kanıtlamalıdır. Hiçbir zaman FF11 veya Chrome 17.

while(true){} 
alert("sucks"); 

http://jsfiddle.net/JCKRt/1/

Sen JavaScript senkron ekstreleri hakkında sorulan içinde alert() çağırır. alert(), confirm(), eşzamanlı ajax çağrıları ve daha fazlası gibi JavaScript'in çalışmasını engelleyecek diğer birkaç eşzamanlı ifade vardır.

Genellikle JavaScript'te herhangi bir eşzamanlı şeyden kaçınmak istersiniz! İşlerin duraklamasını istiyorsanız, tasarımı yeniden düşünmek isteyebilirsiniz. JavaScript olay tahrikli olduğunu. Bir süre içinde dönmeye ihtiyacınız yok, çünkü sayfadaki hiçbir şey sayfada tıklamalar gibi herhangi bir etkinlik de dahil olmak üzere çalışacaktır.

+0

İlgili: https://bugzilla.mozilla.org/show_bug.cgi?id=340345 Artık bir XHR işlemi devam ederken, zamanlayıcıları takmak için Mozilla'da en az bir özel durum var, ama genel durum daha az açık. – ephemient

+2

Bunu "yüzüne yumrukla" düzenledim ... – Timothy003

+0

Bir süre döngüsünü döndürmeniz gerekiyorsa - UI olaylarını engellemeden - bir web çalışanı kullanabilirsiniz: https: //developer.mozilla.org/En/Using_web_workers # Performing_computations_in_the_background –

0

Olaylarla uğraşmaya başladığınızda sorunun ortaya çıkacağını düşünüyorum.

Bir while döngüsü kullanmak yerine, özyinelemeli bir işlev kullanmayı düşünün.

İstediğiniz şekilde çalışması gereken kodunuzda yaptığım bazı değişiklikler.

<head> 
    <script> 
    function loop(that) { 
     var cond; 
     that.onblur = function (event) { 
      cond = false; 
     }; 
     cond = true; 
     var loop = 0 
     var xy = function x(){ 
      if(cond == true){ 
       loop++;   
       setTimeout(function(){xy()},0); 
      } else { 
       alert('loop exited! - '+loop); 
       return true; 
      } 
     } 
     xy(); 
    } 
    </script> 
</head> 
<body> 
    <button onclick="this.focus(); loop(this)">loop()</button> 
</body> 

setTimeout() öğesinin 0 gecikme ile kullanılması, herhangi bir olayın sorunsuz şekilde atlanmasına izin vermelidir. Döngü kodunuz neredeyse hızlı bir şekilde yürütülmeyecek, ancak bunu test etmeniz ve görmeniz gerekecek.