2016-09-03 68 views
2

我有以下JavaScript。附加的代碼是相當複雜的自動生成的JavaScript的極其簡化版本,它在許多對象上啓動相同的功能(不是循環的,而是生成一堆函數調用)。JavaScript不會更新由按鈕觸發的重複操作的狀態分區

問題是代碼應該在每次啓動函數時更新一個元素。但是,這並沒有發生。相反,當我按下按鈕時,只有在執行完所有功能(「完成」)後,它纔會凍結並更新狀態。那麼,爲什麼不能在下面的代碼更新的元素上的long_function()每次調用(和我怎麼解決這個問題):

<html> 
    <body> 
     <h1 id="status">Not yet started</h1> 
     <button onclick="perform()"> Start! </button> 

     <script type="text/javascript"> 
      function sleepFor(sleepDuration){ 
       var now = new Date().getTime(); 
       while(new Date().getTime() < now + sleepDuration){ /* do nothing */ } 
      } 

      function long_function(number) 
      { 
       document.getElementById("status").innerHTML = number; 
       sleepFor(1000); 
      } 

      function perform(number) { 
       long_function(1); 
       long_function(2); 

       document.getElementById("status").innerHTML = "Done"; 
      } 
     </script> 
    </body> 
</html> 

(休眠功能是(這個問題在谷歌Chrome和Safari發生)從答案What is the JavaScript version of sleep()?

回答

1

這是我的理解發生了什麼考慮:

  1. 功能perform()運行,並呼籲首先是。
  2. innerHTML呼叫被髮送。
  3. sleepFor(1000)函數被調用,但瀏覽器尚未呈現innerHTML更改。
  4. 活編譯貫穿while迴路sleepFor(),這是阻擋自然(停止其他JavaScript代碼運行,但它也從渲染停止瀏覽器)。
  5. 一旦while循環完成,JavaScript繼續將您的元素的innerHTML設置爲「完成」,但它永遠不會渲染的long_function()

如果你想在事件循環的有趣的手錶,阻塞和無阻塞的JavaScript,這裏有一些資源:

http://latentflip.com/loupe/

這個問題是因爲標題有點誤導(innerHTML實際上並不是異步運行),但答案很有趣:

innerHTML can't be trusted: Does not always execute synchronously