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