Ajax与弹窗被浏览器拦截(windows.open)的问题

        最近在项目中有这样一个需求:在前端页面的js文件中从后台获取一个URL,拿到URL后调用windows.open方法打开这个URL。URL由后端程序拼接而成,在开发过程中遇到了两个问题,前端js代码如下:

 showWindow : function() {
                Fw.Ajax.request({
                    url : '/ebank/callCenter.do',
                    params : {'COMPY_NAME':COMPY_NAME},
                    page : false,
                    success : function(data) {
                        callCenterUrl = data.call_center_url;   
                    },  
                    if(callCenterUrl != null) {
                        window.open(callCenterUrl,'_blank','width=850, height=600, resizable=yes, toolbar=no, menubar=no');                                             
                        }else {
                            alert("客服系统繁忙,请稍后再试");
                        }               
                    onFailure : function() {
                    },                  
                });         
        },

1.可能出现先弹出窗口,后拿到URL的情况

  • 上面代码经常出现打开空白页面的结果,分析原因是Ajax异步请求后端,还没拿到URL就执行了windows.open方法导致打开了空白页(URL初始值赋的“_blank”)
  • 尝试解决了一下,将弹窗逻辑放在回调函数success中,确实可以保证先拿到URL后再执行windows.open方法,但是又引出了一个新的问题。

2.浏览器拦截弹窗问题

  • 将弹窗逻辑放入Ajax的回调函数success中后,弹出窗口在IE浏览器遭到拦截:
           其原因是浏览器出于安全策略阻挡了非用户点击弹出的窗口,所谓非用户点击就是弹出的窗口不是直接由用户点击事件触发的弹窗。在这段逻辑当中,弹窗事件由程序发起,所以会被浏览器拦截。然而对于用户来说这种体验肯定是不好的,你不能指望一个用户对浏览器以及程序了如指掌。于是通过搜索找到一种解决方法,更新后的代码如下:
showWindow : function() {
            //先打开窗口,防止放进Ajax中被浏览器拦截
            var adPopup = window.open(callCenterUrl,'_blank','width=850, height=600, resizable=yes, toolbar=no, menubar=no');
                Fw.Ajax.request({
                    url : '/ebank/callCenter.do',
                    params : {'COMPY_NAME':COMPY_NAME},
                    page : false,
                    success : function(data) {
                        callCenterUrl = data.call_center_url;   
                        if(callCenterUrl != null) {
                            //避免被浏览器拦截,重定向窗口
                            adPopup.location = callCenterUrl;   
                        }else {
                            alert("客服系统繁忙,请稍后再试");
                        }
                    },  
                    
                    onFailure : function() {
                    },                  
                });         
        },
  • 上述JS代码将打开窗口动作放在了监听按钮点击事件下,在Ajax函数执行之前,我在项目本地加了一个loading动画的页面,在拿到真正后台传来的URL之前,弹出的窗口都会在这个Loading页面等待。一旦Ajax返回了真正的URL,再将窗口重定向到新的URL。经过这种设置,成功解决了弹窗被浏览器拦截的问题。

3.对Ajax的好奇与初步探索

  • Ajax是什么
    AJAX is not a programming language. It is just a technique for creating better and more interactive web applications.
    AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
    AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
    AJAX 是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下刷新局部页面。
  • Ajax怎么实现的
    • 实际使用了几次Ajax与后台进行交互后,我不禁在想,这么好用的技术是怎么实现的?初步猜测是另起了一个线程,在子线程里进行操作,然后在子线程里对局部页面进行更新。
    • 经过搜索,得知Ajax请求的核心是XMLHttpRequest ,原来整个Ajax与后台交互与刷新局部页面的技术是这个对象。对于XMLHttpRequest的介绍有很多,这里仅贴Ajax实现封装以辅助自己记忆。代码来自 AJAX的实现原理以及封装
var $={
    /*传递参数对象,返回拼接之后的字符串*/
    /*{‘name’:’jack,’age’:20}=>  name=jack&age=20&*/
    getParmeter:function(data){
        var result="";
        for(var key in data){
            result=result+key+"="+data[key]+"&";
        }
        /*将结果最后多余的&截取掉*/
        return result.slice(0,-1);
    },
    /*实现ajax请求*/
    ajax:function(obj){
        /*1.判断有没有传递参数,同时参数是否是一个对象*/
        if(obj==null || typeof obj!="object"){
            return false;
        }
        /*2.获取请求类型,如果没有传递请求方式,那么默认为get*/
        var type=obj.type || 'get';
        /*3.获取请求的url  location.pathname:就是指当前请求发起的路径*/
        var url=obj.url || location.pathname;
        /*4.获取请求传递的参数*/
        var data=obj.data || {};
        /*4.1获取拼接之后的参数*/
        data=this.getParmeter(data);
        /*5.获取请求传递的回调函数*/
        var success=obj.success || function(){};

        /*6:开始发起异步请求*/
        /*6.1:创建异步对象*/
        var xhr=new XMLHttpRequest();
        /*6.2:设置请求行,判断请求类型,以此决定是否需要拼接参数到url*/
        if(type=='get'){
            url=url+"?"+data;
            /*重置参数,为post请求简化处理*/
            data=null;
        }
        xhr.open(type,url);
        /*6.2:设置请求头:判断请求方式,如果是post则进行设置*/
        if(type=="post"){
            xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
        }
        /*6.3:设置请求体,post请求则需要传递参数*/
        xhr.send(data);

        /*7.处理响应*/
        xhr.onreadystatechange=function(){
            /*8.判断响应是否成功*/
            if(xhr.status==200 && xhr.readyState==4){
                /*客户端可用的响应结果*/
                var result=null;
                /*9.获取响应头Content-Type ---类型是字符串*/
                var grc=xhr.getResponseHeader("Content-Type");
                /*10.根据Content-Type类型来判断如何进行解析*/
                if(grc.indexOf("json") != -1){
                    /*转换为js对象*/
                    result=JSON.parse(xhr.responseText);
                }
                else if(grc.indexOf("xml") != -1){
                    result=xhr.responseXML;
                }
                else{
                    result=xhr.responseText;
                }
                /*11.拿到数据,调用客户端传递过来的回调函数*/
                success(result);
            }
        }

    }
};

调用方式与jquery类似的:
$.ajax({
    url:'',
    type:'',
    data: {},
    success:function(result){
        //code...
    }
});
  • Ajax出现已经有近20历史,是否有替代技术?
    • 通过我的搜索,发现了一个传说中将会取代Ajax的技术,叫做Fetch,当然了,具体能不能取代Ajax可能还要继续观察,但是对于这技术了解一下总是好的。
  • 引用W3C School的一段话:十多年来,XMLHttpRequest 对象一直被 AJAX 操作所接受,但是我们知道,XMLHttpRequest 对象的 API 设计并不是很好,输入、输出、状态都在同一个接口管理,容易写出非常混乱的代码。那么Fetch API就应势而生,提供了一种新规范,用来取代善不完美的 XMLHttpRequest 对象。
    Fetch API 主要有两个特点:一是接口合理化,AJAX 是将所有不同性质的接口都放在 XHR 对象上,而Fetch是将它们分散在几个不同的对象上,设计更合理;二是Fetch操作返回 Promise 对象,避免了嵌套的回调函数。
    接下来将花点时间学习一下Fetch,先附上Fetch API官方文档
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,928评论 6 509
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,748评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,282评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,065评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,101评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,855评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,521评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,414评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,931评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,053评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,191评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,873评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,529评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,074评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,188评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,491评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,173评论 2 357

推荐阅读更多精彩内容

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,491评论 1 45
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_X自主阅读 15,982评论 3 119
  • 有一天下午,小明在楼下玩,树上有一只小鸟在学飞,一不小心掉在树桩上,被小明抓住了,小明拿来一根绳子,拴住小鸟的...
    谢晨俊阅读 262评论 0 0
  • 秋天的景色,是如此凄美和萧条。 天已近黄昏,惟有几棵老树屹立于此。树杆上刻着时间的印记,树叶也无影无踪了。唯有那枯...
    qqyzyylwmdqc阅读 171评论 0 0
  • 小梅绝对是个美人。高挑、丰满、妩媚,脾气好、与世无争,是个烂好人,任何人都能和她融洽相处。 小梅和老公大伟在同一个...
    小玩具妈妈阅读 3,231评论 86 75