4 回答

TA贡献1850条经验 获得超11个赞
你是不是开着控制台进行测试的,刚刚用chrome测试了一下,如果开着控制台并且控制台取得了焦点,alert不会立即阻塞正在运行的线程,得等到焦点从控制台重新回到页面才会发出alert并阻塞线程;但如果在执行alert之后立即修改window.location.href,此时控制台又取得了焦点,则alert不会立即阻塞线程,jvm转而执行下一个语句修改window.location.href,而这将导致之前尚未发出的alert被取消(我猜的)。
结论是,不要开着控制台测试这段代码。
以下是我的测试代码:
setTimeout(() => $.ajax({
url: '/',
type: 'GET',
success: data => {
console.log('Before rua');
alert('Rua!');
console.log('After rua');
window.location.href += '#';
},
error: (...args) => console.log(...args)
}), 1000);
如果你在1秒内没有将焦点切回页面,则alert不会发出,且window.location.href将被立刻修改;若你在1秒内将焦点切回页面,则alert发出,且window.location.href将会在你将alert dismiss掉后被修改。
或者更简单粗暴一点:
setTimeout(() => {
console.log('Before rua');
alert('Rua!');
console.log('After rua');
window.location.href += '#';
}, 1000);
同上,1秒内切回页面就能看到alert,dismiss后window.location.href才会被修改,反之alert会被取消。
与上述代码之对比:
setTimeout(() => {
console.log('Before rua');
alert('Rua!');
console.log('After rua');
// window.location.href += '#';
}, 1000);
这里只是发出一个alert,并没有修改window.location.href,在控制台输入上述代码并运行后等待一秒,看到控制台输出了“Before rua”和“After rua”,这时再将焦点切回页面,才会看到一个alert弹出。
综上,我猜测alert其实也可以是异步的——当渲染进程检测到当前页面没有获取到焦点时,比如被用户最小化了,此时若页面中嵌入的js试图发出alert,则渲染进程不会立刻弹出alert,而是将请求放入一个队列中(pending),等待下一次获取焦点时再一一弹出。
补充一下,目前使用chrome测试的结果是只有在焦点被控制台获取时发出alert,并且在alert之后修改了window.location.href(焦点仍在控制台),才会把alert直接取消掉。最小化浏览器的话浏览器会自动跳出来发出alert。
添加回答
举报