Firefox a.click 没有断点就不会启动

Firefox a.click won't fire without a breakpoint

我正在做一个项目,我们有一个 AJAX 调用,它以包含 excel 文件的 blob 响应。我希望代码在收到响应时以下载方式打开文件。这是回调:

var blob = new Blob([response.data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
var objectUrl = URL.createObjectURL(blob);
var a = document.createElement("a");
var header = response.headers("Content-Disposition");
a.download = header.substring(header.indexOf("filename=") + "filename=".length);
a.href = objectUrl;
document.body.appendChild(a);
console.debug("Clicking a tag");
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(objectUrl);

此代码在 chrome 中运行良好,但在 firefox 中,当 a.click() 触发时没有任何反应。调试语句打印出来,所以我知道回调正在发生。另外,出于某种原因,如果我在 a.click() 上放置一个断点,它会完美地工作。

有人可以解释为什么点击只能在调试模式下工作吗?

Firefox 有一些保护措施或只是针对此类事情的奇怪行为。我不知道推导过程,但在点击之前返回浏览器片刻通常会清除它:

// ...
a.href = objectUrl;
document.body.appendChild(a);
setTimeout(function() {
    a.click();
    document.body.removeChild(a);
    window.URL.revokeObjectURL(objectUrl);
}, 0);
// ...

请注意 setTimeout 之后的代码将 运行 之前 setTimeout 的内容。

您甚至可能需要两个:

// ...
a.href = objectUrl;
document.body.appendChild(a);
setTimeout(function() {
    a.click();
    setTimeout(function() {
        document.body.removeChild(a);
        window.URL.revokeObjectURL(objectUrl);
    }, 0);
}, 0);
// ...