如何等待 Ajax 请求结束后打开新窗口而不被浏览器屏蔽?
假设这样一个场景:用户点击一个按钮,此时需要请求后端接口进行数据实时校验,如果校验通过则弹出新窗口并打开某个特定的 URL,如果校验失败则给出错误提示并停留在当前页面不做任何处理。
一般情况下,你可能会直觉想到这样去做,但显然问题没有这么简单,尝试后你会发现现代浏览器会屏蔽 Ajax 回调中的弹出窗口:
$('.button').on('click', function() {
$.ajax({
url: '/',
success: function (data) {
if (data) {
window.open('http://www.baidu.com');
}
}
});
});
针对 IE 浏览器,解决办法很简单,只需要封装一个通用方法,通过创建一个 a 标签并模拟触发其点击事件即可:
function openwin(url) {
var a = document.createElement("a");
a.setAttribute("href", url);
a.setAttribute("target", "_blank");
a.setAttribute("id", "camnpr");
document.body.appendChild(a);
a.click();
}
openwin('http://www.baidu.com');
但对于 Chrome 等现代浏览器,这种方法就不那么凑效了:
Modern browsers will allow popups when they're launched from an event loop triggered by an explicit user action. Thus, it's perfectly OK (ignoring web design best practices) to open up something like a "Help" section for your website in a separate window if that happens when the user clicks a "Help Me!" button. Also, it's become quite common for sites to use in-page "pseudo windows" to jam content in front of hapless visitors, and browsers really can't do anything to stop that.
这是因为现代浏览器会屏蔽非用户明确触发的弹出窗口,但还是有 Hack 方法可以解决,在按钮点击后执行 setTimeout 并延时打开新窗口,之后根据 Ajax 的结果去判断是否 clearTimeout:
$('.button').on('click', function() {
setTimeout(function() {
window.open('http://www.baidu.com')
}, 1000);
});
以上只是介绍下思路,以下是更完整的解法和代码:
$('.btn').on('click', function() {
var ajax = new $.Deferred();
$.ajax({
url: '/',
success: function (data) {
if (data) {
ajax.resolve();
}
}
});
openNewWin('http://www.baidu.com', ajax);
});
function openNewWin(url, ajax, waiting) {
var stack = [], current = 0;
waiting = waiting > 0 ? waiting : 5;
for (var i = 1; i < waiting; i++ ) {
stack.push(setTimeout(function() {
if (ajax.state() == "resolved") {
$.each(stack, function (key, val) {
console.log(val);
clearTimeout(val);
});
window.open(url);
} else {
stack.shift();
}
}, i * 1000))
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论