1. 緒論:
AJAX技術(shù)的核心為XHR(XMLHttpRequest)對象
AJAX功能:向服務器請求額外的數(shù)據(jù)而無需卸載頁面,帶來更好的用戶體驗。
2. XHR對象:
XHR對象功能:取得新數(shù)據(jù),并通過DOM將新數(shù)據(jù)插入到頁面中。
如何創(chuàng)建:
var xhr = new XMLHttpRequest();
2.1 XHR用法:
A. 首先調(diào)用open()啟動一個請求準備發(fā)送,接收的三個參數(shù)為請求類型、url、是否異步;
B. send()為發(fā)送特定的請求,如果不需要請求方發(fā)送數(shù)據(jù),則為null;
C. 收到相應后,相應的數(shù)據(jù)填充到xhr對象的屬性中:
responseText : 作為響應的主體被返回的文本
responseXML: 若響應內(nèi)容未XML類型,則保存響應的XML DOM 文檔
status:響應的HTTP狀態(tài)
status:對上述HTTP狀態(tài)的說明
響應成功的標志:HTTP狀態(tài)為200到300之間,或者為304(資源未修改)
同步請求:
var xhr=new XMLHttpRequest();
xhr.open("get","15.html",false);
xhr.send(null);
if((xhr.status>=200 && xhr.status<300) || xhr.status==304){
alert(xhr.responseText)
}
else {
alert("請求失敗")
}
異步請求:讓JS繼續(xù)執(zhí)行,不需要等待響應。
通過檢測xhr對象的readyState屬性查看請求和響應的當前活動階段:
0:未初始化,還沒有調(diào)用open
1:啟動,調(diào)用open,沒有調(diào)用send
2:發(fā)送,調(diào)用send,還沒有收到響應
3:接收,接收到部分響應數(shù)據(jù)
4:完成,接收到全部數(shù)據(jù)
readyState值的變化會觸發(fā)readystatechange事件,從而通過監(jiān)聽該事件來判斷是否接收完成。
var xhr=new XMLHttpRequest();
xhr.open("get","15.html",true);
xhr.send(null);
xhr.onreadystatechange=function () {
if(xhr.readyState==4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText)
}
else {
alert("請求失敗")
}
}
}
2.2 HTTP頭部信息:
每個HTTP請求和響應都有頭部信息。
頭部信息包含了瀏覽器的一些設置,比如瀏覽器能夠處理的內(nèi)容類型、瀏覽器能夠顯示的字符集等。還包括請求頁面所在的域,請求頁面的URI等等。
設置頭部信息:
頭部信息可以通過xhr對象的setRequestHeader()設置自定義的頭部信息,位置必須在open之后send之前。
xhr.open("get","15.html",false);
xhr.setRequestHeader("myii","lingyun");
xhr.send(null);
獲取頭部信息:
var getMYII=xhr.getResponseHeader("myii");
var getALL=xhr.getAllResponseHeaders();
2.3 GET請求
向服務器獲取信息。
其中請求的URL中的?后面放置傳遞的參數(shù),參數(shù)間用&連接。
向URL中添加參數(shù)的函數(shù):
function addURLParam(url,name,value) {
if(url.indexOf("?")==-1){
url+="?"
}else {
url+="&"
}
url+=encodeURIComponent(name)+"="+encodeURIComponent(value);
return url;
}
2.4 POST請求
向服務器發(fā)送應該保存的數(shù)據(jù)。
向服務器提交表單數(shù)據(jù):
function submitData() {
var xhr=new XMLHttpRequest();
xhr.onreadystatechange=function () {
if(xhr.readyState==4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText)
}
else {
alert("請求失敗")
}
}
};
xhr.open("post","url","true");
xhr.setRequestHeader("Content-Type","application/x-www-fowm-urlencoded");//http頭部信息,內(nèi)容類型
var form=document.getElementById("form");
xhr.send(serialize(form));//表單序列化
}
3. XMLHttpRequest 2級
對一級的進一步擴展。
3.1 FormData
為序列化表單以及創(chuàng)建與表單格式相同的數(shù)據(jù)提供了便利。
xhr.open("post","url","true");
xhr.setRequestHeader("Content-Type","application/x-www-fowm-urlencoded");//http頭部信息,內(nèi)容類型
var form=document.getElementById("form");
xhr.send(new FormData(form));//表單序列化
3.2 超時設定
XHR對象有timeout屬性,當超過該值時,瀏覽器沒有收到響應,則觸發(fā)ontimeout事件。
xhr.open("get","url","true");
xhr.timeout=1000;
xhr.ontimeout=function () {
alert("請求超時")
};
xhr.send(null);
4. 進度事件
進度事件是客戶端服務器通信相關(guān)的事件,只針對XHR操作。
總共有6個進度事件:
loadstart: 接收響應數(shù)據(jù)的第一個字節(jié)時觸發(fā);
progress:接收響應期間持續(xù)不斷的觸發(fā);
error:請求發(fā)生錯誤觸發(fā);
abort:調(diào)用abort()方法終止連接時觸發(fā);
load:接收到完整響應數(shù)據(jù)觸發(fā);
loadend:通信完成或者觸發(fā)error abort load事件后觸發(fā)。
5. 跨源資源共享CORS:
通過XHR實現(xiàn)AJAX通信的限制:跨域安全策略。
CORS定義了在跨域請求時,瀏覽器與服務器應該如何溝通。
基本思想:在HTTP頭部自定義源信息(協(xié)議、域名、端口),從而決定請求或響應是否應該成功。
發(fā)送請求時,在頭部添加orgin頭部,包含請求頁面的源信息,以便服務器根據(jù)頭部信息確實是否響應。
需要在服務器端設定Http頭部信息,JS操作不了。
Access-Control-Allow-Origin: http://wwww.nca.net
除了IE之外,其他瀏覽器的XHR對象實現(xiàn)了對CORS的原生支持,無需編寫額外代碼。
6. 其他跨域技術(shù):
6.1 圖像Ping
單向通信,常用于跟蹤用戶點擊頁面或者動態(tài)廣告的曝光次數(shù)。
var image=new Image();
image.onload=image.onerror=function () {
alert("加載完畢")
};
image.src="http://photocdn.sohu.com/20160720/Img460039751.jpeg";
6.2 JSONP
JSONP即被包含在函數(shù)調(diào)用中的JSON:
callback({"name" : "guo"})
JSONP由兩部分組成:回調(diào)函數(shù)和數(shù)據(jù)。
JSONP通過動態(tài)script元素使用,因為script與img元素類似,有能力不受限制跨域訪問。
6.3 Comet
服務器向頁面推送數(shù)據(jù)。
應用場景:需要實時更新的數(shù)據(jù),體育比賽分數(shù)、股票報價等。
實現(xiàn)方式:長輪詢和流。
長輪詢:瀏覽器發(fā)送請求后,服務器不會立即響應,而是等待數(shù)據(jù)更新后再響應。然后瀏覽器再立即請求。

流:流與輪詢不同的是它只使用一個HTTP連接,瀏覽器發(fā)送一次請求后,服務器會保持這個連接打開,周期性的發(fā)送數(shù)據(jù)。
6.4 服務器發(fā)送事件SSE
SSE是圍繞Comet推出的API。
6.5 Web Sockets
提供了全雙工(雙方可以同時傳遞信息)、雙向通信的信道。使用自定義的協(xié)議,不適用HTTP協(xié)議。
在JS中創(chuàng)建Web Socket后,當取得服務器響應后,連接會由HTTP協(xié)議變?yōu)閃eb Socket協(xié)議。
使用Web Socket協(xié)議而非HTTP協(xié)議的好處為:在客戶端和服務器之間發(fā)送很少量的數(shù)據(jù),減少HTTP字節(jié)級的開銷。
var socket=new WebSocket("ws://www.example.com/server.php");
socket.send("hello");