异步请求后,再window.open打开新窗口被浏览器拦截方案

您所在的位置:网站首页 js异步请求失败重试 异步请求后,再window.open打开新窗口被浏览器拦截方案

异步请求后,再window.open打开新窗口被浏览器拦截方案

2023-10-08 23:03| 来源: 网络整理| 查看: 265

众所周知,在平时button或a标签点击事件触发window.open打开新窗口是没有问题的。而如果在点击事件中先进行一些异步请求再去window.open则会被一些浏览器拦截,如下图所示,原因是命中了浏览器的安全策略,在浏览器看来打开窗口并非用户直接操作导致,有可能是一个广告等并非用户想要看到的内容。那么,是否有一些方案可以避免拦截呢?以下为笔者在解决问题过程中试过的几个方案。

safari浏览器拦截

方案一 模拟a标签点击事件(还是会被一些浏览器拦截)

代码如下:

// 模拟a标签点击事件 function newWin(url) { const a = document.createElement('a'); a.href = url; const event = new MouseEvent('click'); a.dispatchEvent(event); } // 异步请求后,触发a标签点击事件 axios.post('xxxx', { a: '1' }).then((res) => { const { url } = res; newWin(url); })

该方案并没能解决浏览器拦截问题,根本原因还是点击事件非用户所为。

方案二 先window.open打开空白窗口,待异步返回后再填充url

代码如下:

// 先打开新的空白窗口 const winRef = window.open(url, '_blank'); // xxx 为新打开窗口的title,不设置的话新窗口title会出现暂时的”无标题“ winRef.document.title = 'xxx'; axios.post('xxx', { a: 'a' }).then((res) => { const { url } = res; // 将新窗口地址置为url winRef.location.href = url; })

该方案亲测是有效的,可以解决浏览器拦截问题,但是在异步请求期间,新打开的窗口会出现空白页,对用户体验不是太友好。 空白窗口

那么,是否有其他更好的方案呢?

在查阅资料时,发现了一些浏览器是根据用户点击事件之后1秒内是否触发window.open来触发拦截的。那么基于此可以通过设置setTimeout 1s时间再触发window.open减少新空白窗口白屏时间,即方案三。

方案三 setTimeout和window.open打开空白页一起使用 let winRef; let targetUrl; // 延迟1000ms setTimeout(() => { winRef = window.open(targetUrl, '_blank'); winRef.document.title = 'xxx'; }, 1000); axios.post('xxx', { a: 'a' }).then((res) => { const { url } = res; // 判断winRef是否有值,如有则已打开了新窗口,则将新窗口地址置为url // 否则将url赋给targetUrl即可 if(winRef) { winRef.location.href = url; } else { targetUrl = url; } })

代码中延迟1000ms为最大延迟时间,如果大于此时间还是会被拦截。但是如果异步接口实际时间小于1000ms,那么可以根据实际情况合理的设置。 此方案在chrome、火狐、safari、360等浏览器亲测有效。

方案四 接入层302跳转

第四种是笔者解决异步跳转比较推崇的方案,即在新开tab中填充url触发get请求,在接入层中完成异步接口请求后,在接入层直接302到目标url。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3