? ? ? ? 最近在項目中有這樣一個需求:在前端頁面的js文件中從后臺獲取一個URL,拿到URL后調(diào)用windows.open方法打開這個URL。URL由后端程序拼接而成,在開發(fā)過程中遇到了兩個問題,前端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("客服系統(tǒng)繁忙,請稍后再試");
}
onFailure : function() {
},
});
},
1.可能出現(xiàn)先彈出窗口,后拿到URL的情況
- 上面代碼經(jīng)常出現(xiàn)打開空白頁面的結(jié)果,分析原因是Ajax異步請求后端,還沒拿到URL就執(zhí)行了windows.open方法導(dǎo)致打開了空白頁(URL初始值賦的“_blank”)
- 嘗試解決了一下,將彈窗邏輯放在回調(diào)函數(shù)success中,確實可以保證先拿到URL后再執(zhí)行windows.open方法,但是又引出了一個新的問題。
2.瀏覽器攔截彈窗問題
- 將彈窗邏輯放入Ajax的回調(diào)函數(shù)success中后,彈出窗口在IE瀏覽器遭到攔截:
? ? ? ?其原因是瀏覽器出于安全策略阻擋了非用戶點擊彈出的窗口,所謂非用戶點擊就是彈出的窗口不是直接由用戶點擊事件觸發(fā)的彈窗。在這段邏輯當(dāng)中,彈窗事件由程序發(fā)起,所以會被瀏覽器攔截。然而對于用戶來說這種體驗肯定是不好的,你不能指望一個用戶對瀏覽器以及程序了如指掌。于是通過搜索找到一種解決方法,更新后的代碼如下:
showWindow : function() {
//先打開窗口,防止放進(jìn)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("客服系統(tǒng)繁忙,請稍后再試");
}
},
onFailure : function() {
},
});
},
- 上述JS代碼將打開窗口動作放在了監(jiān)聽按鈕點擊事件下,在Ajax函數(shù)執(zhí)行之前,我在項目本地加了一個loading動畫的頁面,在拿到真正后臺傳來的URL之前,彈出的窗口都會在這個Loading頁面等待。一旦Ajax返回了真正的URL,再將窗口重定向到新的URL。經(jīng)過這種設(shè)置,成功解決了彈窗被瀏覽器攔截的問題。
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 不是新的編程語言,而是一種使用現(xiàn)有標(biāo)準(zhǔn)的新方法。
AJAX 是與服務(wù)器交換數(shù)據(jù)并更新部分網(wǎng)頁的藝術(shù),在不重新加載整個頁面的情況下刷新局部頁面。 - Ajax怎么實現(xiàn)的
- 實際使用了幾次Ajax與后臺進(jìn)行交互后,我不禁在想,這么好用的技術(shù)是怎么實現(xiàn)的?初步猜測是另起了一個線程,在子線程里進(jìn)行操作,然后在子線程里對局部頁面進(jìn)行更新。
- 經(jīng)過搜索,得知Ajax請求的核心是
XMLHttpRequest,原來整個Ajax與后臺交互與刷新局部頁面的技術(shù)是這個對象。對于XMLHttpRequest的介紹有很多,這里僅貼Ajax實現(xiàn)封裝以輔助自己記憶。代碼來自 AJAX的實現(xiàn)原理以及封裝
var $={
/*傳遞參數(shù)對象,返回拼接之后的字符串*/
/*{‘name’:’jack,’age’:20}=> name=jack&age=20&*/
getParmeter:function(data){
var result="";
for(var key in data){
result=result+key+"="+data[key]+"&";
}
/*將結(jié)果最后多余的&截取掉*/
return result.slice(0,-1);
},
/*實現(xiàn)ajax請求*/
ajax:function(obj){
/*1.判斷有沒有傳遞參數(shù),同時參數(shù)是否是一個對象*/
if(obj==null || typeof obj!="object"){
return false;
}
/*2.獲取請求類型,如果沒有傳遞請求方式,那么默認(rèn)為get*/
var type=obj.type || 'get';
/*3.獲取請求的url location.pathname:就是指當(dāng)前請求發(fā)起的路徑*/
var url=obj.url || location.pathname;
/*4.獲取請求傳遞的參數(shù)*/
var data=obj.data || {};
/*4.1獲取拼接之后的參數(shù)*/
data=this.getParmeter(data);
/*5.獲取請求傳遞的回調(diào)函數(shù)*/
var success=obj.success || function(){};
/*6:開始發(fā)起異步請求*/
/*6.1:創(chuàng)建異步對象*/
var xhr=new XMLHttpRequest();
/*6.2:設(shè)置請求行,判斷請求類型,以此決定是否需要拼接參數(shù)到url*/
if(type=='get'){
url=url+"?"+data;
/*重置參數(shù),為post請求簡化處理*/
data=null;
}
xhr.open(type,url);
/*6.2:設(shè)置請求頭:判斷請求方式,如果是post則進(jìn)行設(shè)置*/
if(type=="post"){
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
}
/*6.3:設(shè)置請求體,post請求則需要傳遞參數(shù)*/
xhr.send(data);
/*7.處理響應(yīng)*/
xhr.onreadystatechange=function(){
/*8.判斷響應(yīng)是否成功*/
if(xhr.status==200 && xhr.readyState==4){
/*客戶端可用的響應(yīng)結(jié)果*/
var result=null;
/*9.獲取響應(yīng)頭Content-Type ---類型是字符串*/
var grc=xhr.getResponseHeader("Content-Type");
/*10.根據(jù)Content-Type類型來判斷如何進(jìn)行解析*/
if(grc.indexOf("json") != -1){
/*轉(zhuǎn)換為js對象*/
result=JSON.parse(xhr.responseText);
}
else if(grc.indexOf("xml") != -1){
result=xhr.responseXML;
}
else{
result=xhr.responseText;
}
/*11.拿到數(shù)據(jù),調(diào)用客戶端傳遞過來的回調(diào)函數(shù)*/
success(result);
}
}
}
};
調(diào)用方式與jquery類似的:
$.ajax({
url:'',
type:'',
data: {},
success:function(result){
//code...
}
});
- Ajax出現(xiàn)已經(jīng)有近20歷史,是否有替代技術(shù)?
- 通過我的搜索,發(fā)現(xiàn)了一個傳說中將會取代Ajax的技術(shù),叫做Fetch,當(dāng)然了,具體能不能取代Ajax可能還要繼續(xù)觀察,但是對于這技術(shù)了解一下總是好的。
- 引用W3C School的一段話:十多年來,XMLHttpRequest 對象一直被 AJAX 操作所接受,但是我們知道,XMLHttpRequest 對象的 API 設(shè)計并不是很好,輸入、輸出、狀態(tài)都在同一個接口管理,容易寫出非常混亂的代碼。那么Fetch API就應(yīng)勢而生,提供了一種新規(guī)范,用來取代善不完美的 XMLHttpRequest 對象。
Fetch API 主要有兩個特點:一是接口合理化,AJAX 是將所有不同性質(zhì)的接口都放在 XHR 對象上,而Fetch是將它們分散在幾個不同的對象上,設(shè)計更合理;二是Fetch操作返回 Promise 對象,避免了嵌套的回調(diào)函數(shù)。
接下來將花點時間學(xué)習(xí)一下Fetch,先附上Fetch API官方文檔。