Microsoft Edge:setInterval() 回调与 print() 同时调用

Microsoft Edge: setInterval() callback called concurrently with print()

我发现 Microsoft Edge 中似乎存在错误。 setInterval() 的回调有时会在 print() 执行时调用。这导致 2 JavaScript 函数 运行 并行,这是不允许的,对吧?

可以使用这个简单的测试应用程序观察行为。

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

当我单击 "Print" 按钮时,我不希望看到警报,但我确实看到了警报。

环境:Microsoft Edge 38.14393.0.0,Windows10

这是一个错误还是我不明白什么?

是的,这是一个已确认的错误。我有点惊讶,显然没有人在我之前报告过这一点。

https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/10230373/

以下是我解决该错误的方法。

(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 = [];
            }
        }
    }
})();