如何等待 Ajax 请求结束后打开新窗口而不被浏览器屏蔽?

发布于 2021-11-18 12:37:46 字数 2774 浏览 1176 评论 0

假设这样一个场景:用户点击一个按钮,此时需要请求后端接口进行数据实时校验,如果校验通过则弹出新窗口并打开某个特定的 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))
    }
}

Demo:http://jsfiddle.net/agwmfxyc/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

0 文章
0 评论
777 人气
更多

推荐作者

娇女薄笑

文章 0 评论 0

biaggi

文章 0 评论 0

xiaolangfanhua

文章 0 评论 0

rivulet

文章 0 评论 0

我三岁

文章 0 评论 0

薆情海

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文