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閱讀 228,345評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,494評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,283評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,953評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,714評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,410評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,940評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,776評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,210評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,654評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML標準。 注意:講述HT...
    kismetajun閱讀 27,559評論 1 45
  • 1、通過CocoaPods安裝項目名稱項目信息 AFNetworking網絡請求組件 FMDB本地數據庫組件 SD...
    陽明先生_X自主閱讀 16,000評論 3 119
  • 有一天下午,小明在樓下玩,樹上有一只小鳥在學飛,一不小心掉在樹樁上,被小明抓住了,小明拿來一根繩子,拴住小鳥的...
    謝晨俊閱讀 272評論 0 0
  • 秋天的景色,是如此凄美和蕭條。 天已近黃昏,惟有幾棵老樹屹立于此。樹桿上刻著時間的印記,樹葉也無影無蹤了。唯有那枯...
    qqyzyylwmdqc閱讀 175評論 0 0
  • 小梅絕對是個美人。高挑、豐滿、嫵媚,脾氣好、與世無爭,是個爛好人,任何人都能和她融洽相處。 小梅和老公大偉在同一個...
    小玩具媽媽閱讀 3,243評論 86 75