异步请求回调函数中执行window.open被浏览器拦截

window.open被浏览器拦截问题。

  • 非用户触发的操作,调用window.open()打开新的tab页,会被浏览器拦截,浏览器认为这可能是一个广告,不是用户希望看到的页面;

  • 在用户触发事件函数中,调用多个window.open(),第一个不会被拦截,其他的都会被拦截;

  • 在用户触发事件函数中,若有异步请求,在异步请求的回调函数中调用window.open()也会被拦截;

解决方案

定时器(无效)

一开始使用定时器的方式,在异步请求前先设置定时器,判断openUrl有值后再调用window.open。后来发现在请求响应慢的情况下(比如上传成千上万条数据)依然会被浏览器拦截。

1
2
3
4
5
6
timer = window.setInterval(() => {
if (openUrl) {
window.open(openUrl, '_blank')
clearTimer()
}
}, 500)

引导用户操作

如果浏览器拦截了新窗口,引导用户允许网站弹窗或点击链接访问。

1
2
3
4
5
const win = window.open(url)
if (win == null) {
console.log('新窗口被浏览器拦截')
// ... 引导用户
}

打开新页面后再重定向

在用户点击时先打开新的空白页面,再进行异步请求;请求完成后再对新页面进行重定向:

1
2
3
4
5
6
7
8
9
10
11
// 打开新页面,提示正在加载中
const win = window.open()
win.document.write('加载中,请稍候...')
win.document.title = '加载中...'

// ...请求

// 请求成功重定向
win.location = url
// 请求失败关闭新页面
win.close()