记录个人生活
首页
  • 分类
  • 标签
  • 归档

Canson

首页
  • 分类
  • 标签
  • 归档
  • 常用的正则表达式整理
  • 如何解决异步新窗口被拦截的问题
    • 问题描述
    • 原因分析
    • 解决思路
    • 解决方法
  • Javascript
Canson
2021-04-02

如何解决异步新窗口被拦截的问题

在异步操作的回调中通过新窗口打开页面,通常会被浏览器会拦截。这种情况有一个比较好的方法可以规避。

# 问题描述

曾遇到过一个问题。在 ajax 请求回调中使用 window.open 新窗口打开页面的时候,有很大概率被浏览器拦截。当时用的是 360 浏览器,以为是 360 作妖。后来发现在 chrome 上也同样会出现。

已阻止弹出窗口

如果不是异步操作,都是能正常打开,完全不存在被拦截的情况。

以下代码可以很容易复现这种情况。

setTimeout(()=>{
  window.open('https://zcc.ren')
},5000)
1
2
3

# 原因分析

猜测是浏览器认为,异步操作中新窗口弹出的页面不是用户直接触发或主动打开的,所以将其视为广告或者恶意网站之类的,自动拦截。

# 解决思路

既然找到原因了,知道是因为异步操作导致的,那就想办法让它变成同步的操作。

试了几个投机取巧的方法,试图绕开浏览器的这个机制

  • 把新窗口打开页面的操作绑定在一个按钮的点击事件上,请求回调后触发这个按钮的点击事件。
  • 把新窗口页面的地址绑定在设置了 target="_blank" 的 a 标签上,请求回调后触发这个链接的点击事件。
  • 把新窗口页面的地址绑定在设置了 target="_blank" 的表单上,请求回调后提交这个表单。

以上的方法虽然很不优雅,但看起来好像能行。然而还是太年轻了,事实上,这些方法都不行,浏览器还是知道这是异步操作,依然会拦截。

最后想到一个可行又优雅的方法。就是请求前先把新页面打开(同步操作,不会被拦截),请求完成后,再让这个页面跳转到真正的目标页面。

# 解决方法

// 先直接打开跳转页,同步不会被拦截,不设置具体地址,会打开一个 about:blank
const newWindow = window.open()
// 异步操作开始
axios('/xxx')
.then(()=>{
  // 需要异步打开新页面的情况下,url通常都是跟回调数据有关的,这里可以自定义
  newWindow.location.href='https://zcc.ren'
})
.catch(()=>{
  // 错误时关闭页面
  newWindow.close()
})
1
2
3
4
5
6
7
8
9
10
11
12

请求前先打开了一个空白页。等到异步操作完毕之后,如果成功就让这个页面跳转到具体的目标地址,如果失败就将这个页面关闭。

如果等待时间较长,空白页面会呈现比较久。可以考虑新建一个 html 页面来显示 loading。将第一步打开页面的操作指定到这个 loading 的页面。

这样规避了异步新窗口打开页面的操作,不会被拦截,个人认为是比较完美的解决方案。

上次更新: 2022/07/27, 15:36:28
常用的正则表达式整理

← 常用的正则表达式整理

最近更新
01
为 docker pull 设置代理
02-05
02
ubuntu 开启bbr
11-04
03
整合管理过程ITO
10-23
更多文章>
Theme by Vdoing | Copyright © 2019-2025 Canson | 粤ICP备19120614号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式