AJAX
要想要知道AJAX是什么呢,首先要知道一般情況下客戶端都會從服務器獲取了一些什么類型的文件;
- 如果客戶端在服務器需要獲取的是資源文件,瀏覽器會自動幫我們向服務器發(fā)送請求,并且接收服務器返回的內容進行渲染,最終顯示出來;(這里的資源文件包括JS,HTML,CSS,IMG等類型)
向服務器發(fā)送請求資源文件基本可通過:
- 在地址欄輸入網址
- 利用LINK
- 利用SCRIPT
- 利用IFRAME
- ...
- 但是如果我們需要向服務器請求的是數據(這里的數據可能是json、text、xml等格式的),就需要使用AJAX等技術發(fā)送請求了(AJAX是JS中的一個核心重要知識點)
‘AJAX 不是新的編程語言,而是一種使用現(xiàn)有標準的新方法?!? ---W3C的官方解釋
所以什么是AJAX:
AJAX: Async(Asynchronous) JavaScript And Xml
翻譯過來就是 :異步的JavaScript和Xml
來自W3C的解釋:
AJAX 是一種用于創(chuàng)建快速動態(tài)網頁的技術。通過在后臺與服務器進行少量數據交換,AJAX 可以使網頁實現(xiàn)異步更新。這意味著可以在不重新加載整個網頁的情況下,對網頁的某部分進行更新。
- 那么什么又是XML
- AJAX叫做異步更新,難道使用異步請求嗎?
掃盲1 : 什么是XML
- html :超文本標記語言,W3C制定了很多具有語義化的標記標簽,我們使用這些HTML標簽搭建頁面結構(目前用的比較多的是 v4/v5(HTML5)版本)
- xhtml:更加嚴格的HTML (用的比較少了)
- dhtml:頁面中的數據是動態(tài)綁定的 (非官方標準語言)
- xml :可擴展的標記標簽語言,它里面使用的標簽都是自己定義的,也不是W3C的規(guī)范標簽
- 我們可以使用自己定義的有意義的標簽來存儲數據,這樣結構清晰明了(目前前端數據存儲和展示一般都使用JSON,但是之前一般都是XML)
以前項目中服務器返回給客戶端的數據類型一般都是XML格式的,只不過XML格式的數據在客戶端的二次解析過程中相對于JSON比較麻煩,現(xiàn)在服務器端返回給客戶端的數據一般都是JSON格式的數據;但是也有XML格式的數據;
- wxml:微信小程序的頁面就是.wxml ,小程序中使用的標簽都是小程序自己定義的(微信XHML)
掃盲2 :異步JS -> 異步更新
在web1.0 web2.0時代初期, ==> 整體刷新
前端頁面中的功能和數據綁定大部分都是后臺開發(fā)者使用后臺語言來完成的;瀏覽器只有一個作用,就是把后臺實現(xiàn)好的功能的頁面呈現(xiàn)即可,所有的操作都是后臺在服務器完成的;這樣的話如果前端頁面中的內容需要改變的話,必須后臺重新把最新的內容返回,前端需要重新呈現(xiàn),導致整個前端頁面都刷新;
AJAX 里的Async(異步)先不要理解為JS中的同步異步編程(這樣會很混亂),這里面的異步可以先理解為‘局部刷新’,如果用七個字概述AJAX的作用,那就記住 “實現(xiàn)局部刷新的” 就Ok了;
舉一個非常簡單的運用AJAX的例子:
注冊百度賬號頁面中,
【運用AJAX】注冊過程中,如果填寫一個已經被注冊的手機號,此時,在點擊驗證碼選框時,該手機號的數據內容便會傳送到服務器端進行驗證,會立馬彈出此手機已經被綁定過的提示框;
【沒有運用AJAX】整個數據傳輸過程中不會有任何提示框出現(xiàn),只有在全部表單填寫完成點擊注冊后完成一次數據傳輸,與服務器建立連接進行確認,如果此時該手機被注冊的話,整個注冊頁面會被重新刷新后才會返回該手機被綁定的數據信息,并且之前表單中填寫信息都在刷新后清空,體驗極差,所以一般此類頁面為了增加用戶體驗都會運用到AJAX;當然還有很多運用場景...
簡單實現(xiàn)AJAX的基本步驟
1、 創(chuàng)建AJAX對象
var xhr = new XMLHttpRequest(); // ->IE6 下不兼容 不兼容用 new ActiveXObject
2 、打開一個請求的URL地址
xhr.open([method],[request url],[async/sync]);
- [method] : 請求方式分為兩大系列:
- get系列:
- get : 獲取 (應用于從服務器端獲取內容)
- delete :刪除,應用于刪除服務器上的內容
- head :應用于只想獲取服務器響應頭信息
- post系列:
- post : 推送,應用于給服務器推送內容
- put : 放,應用于在服務器上放文件等
- ...
- 還有更多的請求方式
ps: 以上的幾種方式,客戶端都可以把內容傳遞給服務器,服務器也可以把內容返回給客戶端,只不過在不同的場景,我們使用對應的類型會更好一些,以上沒有硬性規(guī)定,方式可以互換。只不過大家形成了一種約定俗成的默契,例如:
給服務器少,從服務器拿的多,我們最好用GET請求
給服務器多,從服務器拿的少,我們最好用POST請求
get請求和post請求的區(qū)別:
核心:
- get請求傳遞給服務器的內容是通過問號傳參的方式傳遞的;
xhr.open('get','temp.json?xxx=xxx&xxx=xx') - post傳遞給服務器的內容是用過請求主體傳遞的 ;
xhr.send(...)
(1) GET傳遞給服務器的內容沒有POST請求多 :
每一個瀏覽器對url的長度都有限制(谷歌8kb、火狐7kb、ie2kb),如果get請求下傳遞的比較多,url就會超出限制,超出的限制部分瀏覽器自動截取,導致服務器獲取的內容不完整;
而請求主體中的大小理論上是沒有限制的,但真實項目中為了保證傳輸的速度,我們會限制傳遞內容的大小.
(2) GET請求容易出現(xiàn)緩存 :
還是因為使用問號傳參的方式,如果重復向同一個地址發(fā)送請求,傳遞的參數值都是一樣的,瀏覽器會默認的給做緩存(這個緩存不可控),所以我們一般項目中在使用get請求的時候都要把緩存清除掉;
xhr.open('get','temp.json?_='+Math.random());
(3) GET請求相對于POST來說不安全 :
有一種黑客技術叫做‘url劫持’,被劫持后,問號后面的參數值都會被獲取或者修改,導致不安全
- [request url] :請求數據的接口地址,客戶端也是通過這個地址向服務器發(fā)送請求的,客戶端可以通過問號傳參的方式吧內容傳遞給服務器;
xhr.open('get','temp.json?name = zhangsan&age=18',true);
-
[async/sync] : 同步或者異步,默認true 代表異步,可不寫;
在真實項目中,為了防止出現(xiàn)請求堵塞的問題,我們大部分采用的是異步
比如請求文件比較大,如果時間很長,響應時間比較長就會影響后面的數據
3 、監(jiān)聽AJAX狀態(tài)改變,在不同的狀態(tài)下處理不同的事情
xhr.onreadystatechange = function(){
if(xhr.readyState===4 && xhr.status ===200){
var val = xhr.responseText;
// -> xhr.getResponseHeader([key]) 獲取響應頭信息
// -> xhr.responseText: 獲取的是字符串(一般是服務器響應主體
//返回的JSON字符串)
// -> xhr.responseXML: 獲取的是XML數據
}
}
xhr.readyState :AJAX狀態(tài)碼
0 UNSENT : 未發(fā)送,剛開始創(chuàng)建完成AJAX對象,默認的狀態(tài)就是0
1 OPENED : 已打開,執(zhí)行了xhr.open之后狀態(tài)變?yōu)?
2 HEADERS_RECEIVED :響應頭信息已經成功的返回并且被接收
3 LOADING : 響應主體內容正在加載
4 DONE :響應主體內容接收成功
- xhr.status : 服務器返回的HTTP網絡狀態(tài)碼
200 : 請求成功
【 3 開頭的都是成功但是有轉折】
301 : 永久重定向(永久轉移) 例如:訪問京東以前的域名www.360buy.com;
在控制臺network里,可以看到301,域名更換的時候我們基本上都會做301做永久的重定向;
302 : 臨時重定向(臨時轉移) --> 307(臨時重定向) ;例如:一臺服務器最高并發(fā)數在500左右,當501個人過來的時候,當前服務器不能有效的進行處理了,此時我們需要把此客戶端的請求臨時轉移到另外一臺服務器上進行處理;
304 : 讀取的是緩存的數據,在真實的項目中,產品一旦上線,資源圖片、JS、CSS等內容是不輕易改變的,此時我們最好做一下304緩存:第一次向服務器發(fā)送請求來訪問的時候,把加載完成的資源文件進行緩存,第二次直接讀取緩存中的數據即可,減少服務器壓力;
【4開頭的一般都是客戶端的錯誤】
400 請求參數有誤
401 請求的權限不夠
404 請求的地址不存在
【服務器端的錯誤】
500 未知的服務器端錯誤 (停電,著火,服務器爆炸等等不可預知錯誤....)
503 服務器超負荷 (春運搶票的時候你一定會看到這個狀態(tài))
4 、發(fā)送AJAX請求給服務器
xhr.send(null);
// -GET系列請求傳遞的一般都是null,因為他們通過問號傳參把內容傳遞給服務器
// -POST系列的請求會把需要傳遞給服務器的內容放在這里(請求主體);
AJAX整個過程中開始和結束標志事件:
開始的標志:xhr.send(...)
結束的標志:xhr.readyState === 4
利用JQuery 實現(xiàn)AJAX
<script src="jquery.min.js"></script>
$.ajax({
url: 'temp.json',
method: 'get',
//->type:'get' 和這個屬性是一樣的功能的,除了寫get還可以寫post、head、delete、put...
dataType: 'json',
//->預設服務器返回的數據內容的格式json(默認)、text、xml...
data: null,
//->設置請求主體的內容,如果是GET請求,JQ會把這些內容放到請求地址的末尾,通過問號傳參的方式傳遞給服務器,POST請求才是放在請求主體中
cache: true,
//->是否保留GET請求的緩存,TRUE是保留也就是不清除GET緩存,設置成為FALSE是清除緩存(在URL末尾加隨機數),此參數對于POST請求無效
async: true,
//->設置同步異步,默認是TRUE代表異步
//timeout:3000,//->設置請求超時的時間,如果超過3000MS,當前請求自動中斷(一般不用)
success: function (result) {
//->當數據請求成功后執(zhí)行的回調函數,result就是從服務器獲取的結果
console.log(result);
},
error: function (msg) {
//->當數據請求失敗指定的回調函數,msg就是失敗的原因
}
});
// JQ中的參數配置大概在20多個左右,以上只是最常用的幾個
/*
* [data]
* get->放在URL末尾
* post->放在請求主體
*
* 字符串->寫的是什么傳遞就是什么
* 對象->會把對象變成 key1=value1&key2=value2... 傳遞給服務器
*/
最后分享一道面試題:
問:有做過類似于倒計時的項目嗎,做的時候當前時間是從客戶端本地讀取的還是從服務器讀取的?從服務讀取時間你是怎么解決時間差的?
<script>
/*
* 獲取服務器的時間,我們不需要再響應主體中獲取,在響應頭的信息中,
* 有一個叫做Date的屬性,它存儲的值就是服務器的時間
*/
var xhr = new XMLHttpRequest();
xhr.open('head', 'temp.xml?_=' + Math.random());
//->為什么選擇HEAD請求方式?因為當前的需求,我們只想獲取到服務器時間,
//這樣的話只需要把響應頭信息獲取到即可,主體內容不需要獲取了,
//使用HEAD就是只獲取頭信息,加大請求的效率;
xhr.onreadystatechange = function () {
if (xhr.status !== 200) return;
if (xhr.readyState === 2) {
//->我們只需要響應頭信息返回就可以獲取到服務器的時間,如果等到4的時候,
//雖然也可以獲取到,但是間隔的時間更長了,導致時間差也會變大(真實時間和服務器獲取的時間差值)
var time = xhr.getResponseHeader('Date');
//->獲取到的時間是格林尼治時間(GMT),我們還需要把這個時間變?yōu)楸本r間(GMT+0800)
time = new Date(time);
console.log(time);
}
};
xhr.send(null);
</script>
以上就是對AJAX的一個初步的探索啦,這技術出道這么久,一直只聞其名不見其聲的技術,還真有點相見恨晚的趕腳啊....
相信初學者看完此篇應該會對AJAX有一個初步的理解了,目前也探索到這里,一起繼續(xù)探索吧,騷年們,如有異議,歡迎指正~!

