2016-12-14 70 views
1

我發現看起來是Microsoft Edge中的一個錯誤。 setInterval()的回調有時在print()執行時被調用。這導致2個並行運行的JavaScript函數不應該被允許,對吧?Microsoft Edge:與print()併發調用的setInterval()回調

這個簡單的測試應用程序可以觀察到的行爲。

的index.html:

<!DOCTYPE html> 
<html>  
    <head> 
    <script src="script.js"></script> 
    </head> 
    <body> 
    <input type="button" onclick="printPage()" value="Print"/> 
    </body> 
</html> 

的script.js:

var isPrinting = false; 

setInterval(function tick() { 
    if (isPrinting) { 
    alert('Interval callback called conurrently with click handler!'); 
    } 
}, 10); 

function printPage() { 
    isPrinting = true; 
    try { 
    print(); 
    } 
    finally { 
    isPrinting = false; 
    } 
} 

https://plnkr.co/edit/eKMQEHjRiXzl1vzjzIEN

當我點擊 「打印」 按鈕,我不希望看到的警報,但我確實觀察到一個警報。

環境:微軟邊緣38.14393.0.0中,Windows 10

這是bug還是我不懂的東西?

+2

那麼使用警報是一個壞主意調試。你真的想做什麼?間隔的目的是什麼? – epascarello

+1

A在實際應用程序中遇到問題,並將問題縮小到plunkr中的測試用例。如果願意,可以用console.log()替換alert()。我只是覺得警報讓讀者更容易。 – Mike

回答

0

這裏是我如何周圍的錯誤工作。

(function() { 
    var isPrinting = false; 
    var _setInterval = window.setInterval; 
    var _print = window.print; 
    var queue = []; 

    window.setInterval = function (fn, delay) { 
     var params; 
     if (arguments.length > 2) { 
      params = arguments.slice(2); 
     } 
     var wrapper = function() { 
      if (!isPrinting) { 
       fn.apply(null, params); 
      } 
      else { 
       //console.log('queuing...'); 
       // Queue only one callback per setInterval() call. This mimics Chrome and IE11's behavior. 
       if (!wrapper.queued) { 
        wrapper.queued = true; 
        queue.push(wrapper); 
       } 
      } 
     }; 
     _setInterval(wrapper, delay); 
    }; 

    window.print = function() { 
     //console.log('print begin'); 
     isPrinting = true; 
     try { 
      _print.apply(this, arguments); 
     } 
     finally { 
      //console.log('print end'); 
      isPrinting = false; 
      if (queue.length > 0) { 
       var _queue = queue; // Save the contents of the queue so that we have them when the timeout callback executes. 
       setTimeout(function() { 
        _queue.forEach(function (wrapper) { 
         wrapper.queued = false; 
         wrapper(); 
        }); 
       }); 
       queue = []; 
      } 
     } 
    } 
})();