2016-12-14 34 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 = []; 
      } 
     } 
    } 
})();