AJAX
AJAX,即 Asynchronous(異步的) JavaScript and XML。
AJAX不是一門新的語言,而是對現(xiàn)有技術(shù)的綜合運用。
其本質(zhì)是在HTTP協(xié)議的基礎(chǔ)上以異步的方式與服務(wù)器進行通信。
AJAX是一種用于創(chuàng)建快速動態(tài)網(wǎng)頁的技術(shù)。通過在后臺與服務(wù)器進行少量的數(shù)據(jù)交換,AJAX可以使網(wǎng)頁實現(xiàn)異步更新。即在不重載整個網(wǎng)頁面的情況下,對網(wǎng)頁的某部分進行更新。
AJAX 的好處
AJAX 可以實現(xiàn)異步通信效果,實現(xiàn)頁面局部刷新,帶來更好的用戶體驗:按需獲取數(shù)據(jù),節(jié)約寬帶資源。
AJAX 的缺點
- AJAX 不支持瀏覽器的 back 按鈕。
- 安全問題。AJAX 暴露了與服務(wù)器交互的細節(jié)。
- 對搜索引擎的支持比較弱。
- 破壞了程序的異常機制
異步
指某段程序執(zhí)行時不會阻塞其它程序執(zhí)行,其表現(xiàn)形式為程序的執(zhí)行順序,不依賴程序本身的書寫順序,相反則為同步。其優(yōu)勢在于不阻塞程序的執(zhí)行,從而提升整體的執(zhí)行效率。
實現(xiàn)異步加載的方式
- defer 只支持ie
<script type="text/javascript" defer="defer"></script>
- async html5的屬性
<script type="text/javascript" src="" async="async"></script>
- 動態(tài)創(chuàng)建script
function loadScript(url, callback){
var script = document.createElement("script")
script.type = "text/javascript";
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" ||script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others: Firefox, Safari, Chrome, and Opera
script.onload = function(){
callback();
};
}
script.src = url;
document.body.appendChild(script);
}
- 由于javascript的動態(tài)性,還有很多異步加載的方法:XHR Injection、XHR Eval、Script In Iframe、Script defer屬性等等。
- XHR Injection(XHR 注入):通過XMLHttpRequest來獲取javascript,然后創(chuàng)建一個script元素插入到DOM結(jié)構(gòu)中。ajax請求成功后設(shè)置script.text為請求成功后返回的responseText。
另外:實現(xiàn)異步編程有哪些方式。(摘自Javascript異步編程的4種方法)
- 回調(diào)函數(shù) callback
function f1(callback){
setTimeout(function () {
//f1的任務(wù)代碼
callback();
},1000);
}
回調(diào)函數(shù)的優(yōu)點是簡單,易理解和部署,缺點是不利于代碼閱讀和維護,各部分之間高度耦合,流程會很混亂,而且每個任務(wù)只能指定一個回調(diào)函數(shù)。
- 事件監(jiān)聽
f1.on('done', f2);
function f1() {
setTimeout(function () {
//f1的任務(wù)代碼
f1.trigger('done');
}, 1000);
}
這種方法的優(yōu)點是比較容易理解,可以綁定多個事件,每個事件可以指定多個回調(diào)函數(shù),而且可以“去耦合”,有利于實現(xiàn)模塊化。缺點是整個程序都要變成事件驅(qū)動型,運行流程會變得很不清晰。
- 發(fā)布/訂閱
采用的是Ben Alman 的 Tiny Pub/Sub
jQuery.subscribe("done", f2);
function f1() {
setTimeout(function () {
//f1的任務(wù)代碼
jQuery.publish("done")
}, 1000);
}
發(fā)布/訂閱模式(public-subscribe pattern),又稱觀察者模式(observer pattern)。
f1執(zhí)行完成后向信號中心發(fā)布done信號,從而引發(fā)f2的執(zhí)行。
f2執(zhí),行完成后可以取消訂閱。
jQuery.unsubscribe("done", f2);
這種方法的性質(zhì)和“事件監(jiān)聽”類似,但是明顯優(yōu)于后者。因為我們可以通過查看“消息中心”。了解存在多少信號、每個信號有多少訂閱者,從而監(jiān)控程序的運行。
- Promise對象
ES6是由社區(qū)最早提出和實現(xiàn),ES6將其寫進了語言標準,統(tǒng)一了用法,原生提供了Promise對象。
從語法上說,Promise是一個對象,可以獲取異步操作的結(jié)果,它有三種狀態(tài)。
- Pending(進行中)
- Resolved(已完成,又稱Fulfilled)
- Rejected(已失敗)
只有異步操作的結(jié)果,可以決定當前是哪一種狀態(tài)。
一旦狀態(tài)改變,就不會再變,任何時候都可以得到這個結(jié)果。Promise對象的狀態(tài)改變,只有兩種可能: - 從 Pending 變?yōu)?Resolved。
- 從 Pending 變?yōu)?Rejected。
var promise = new Promise(function(resolve, reject) {
if (/* 異步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
promise.then(function(value) {
// success
}, function(error) {
// failure
});
扯遠了...
同步異步的區(qū)別
- 同步:阻塞的
瀏覽器向服務(wù)器請求數(shù)據(jù),服務(wù)器比較忙,瀏覽器一直等著(頁面白屏),直到服務(wù)器返回數(shù)據(jù),瀏覽器才能顯示頁面。 - 異步:非阻塞的
瀏覽器向服務(wù)器請求數(shù)據(jù),服務(wù)器比較忙,瀏覽器可以自如的干原來的事情(顯示頁面),服務(wù)器返回數(shù)據(jù)的時候通知瀏覽器一聲,瀏覽器把返回的數(shù)據(jù)再渲染到頁面,局部更新。
XMLhttpRequest
XMLhttpRequest可以以異步方式的處理程序。
瀏覽器內(nèi)建對象,用于在后臺與服務(wù)器通信(交換數(shù)據(jù)),由此我們便可實現(xiàn)對網(wǎng)頁的部分更新,而不是刷新整個頁面。
一個基本的例子:
//實例化
var xhr = new XMLHttpRequest();
//發(fā)起一個http請求
xhr.open('get', 'index.php');
xhr.send(null);
//接收服務(wù)器響應(yīng)
xhr.onreadystatechange = function () {
if(xhr.readyState == 4 && xhr.status == 200) {
var result = document.querySelector('.result');
result.innerHTML = xhr.responseText
}
}
請求
XMLHttpRequest 本質(zhì)基于 HTTP 協(xié)議實現(xiàn)通信。HTTP 請求 3 個組成部分與 XMLHttpRequest 方法的對應(yīng)關(guān)系:
- 請求行
xhr.open('get', 'index.php')
- 請求頭(get 請求可以不設(shè)置)
xhr.setRequestHeader('Content-Type', 'text/html');
- 請求主體
xhr.send(null);
響應(yīng)
HTTP響應(yīng) 3 個組成部分與 XMLHttpRequest 方法或?qū)傩缘膶?yīng)關(guān)系。
由于服務(wù)器做出響應(yīng)需要時間(比如網(wǎng)速慢等原因),所以我們需要監(jiān)聽服務(wù)器響應(yīng)的狀態(tài),然后才能進行處理。
xhr.onreadystatechange = function () {
if(xhr.readyState == 4 && xhr.status == 200) {
var result = document.querySelector('.result');
result.innerHTML = xhr.responseText;
}
}
onreadystatechange 是 Javascript 的事件的一種,其意義在于監(jiān)聽 XMLHttpRequest 的狀態(tài)。
- 獲取狀態(tài)行(包括狀態(tài)碼和狀態(tài)信息)
xhr.status
xhr.statusText
- 獲取響應(yīng)頭
//獲取指定頭信息
xhr.getResponseHeader('Content-Type');
//獲取所有響應(yīng)頭信息
hr.getAllResponseHeaders();
- 響應(yīng)主體
xhr.responseText;
xhr.responseXML;
我們需要檢測并判斷響應(yīng)頭的 MIME 類型后確定使用 request.responseText 或者 request.responseXML.
創(chuàng)建一個 ajax
var xhr = null;//創(chuàng)建對象
if (window.XMLHttpRequest) {
xhr = new XHLHttpRequest();
}else {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
xhr.open("方式", "地址", "標志位");//初始化請求
xhr.setRequestHeader("","")//設(shè)置相應(yīng)頭信息
xhr.onreadystatechange = function () {}//指定回調(diào)函數(shù)
xhr.send();//發(fā)送請求
簡述ajax的過程
- 創(chuàng)建 XMLHttpRequest 對象,也就是創(chuàng)建一個異步調(diào)用對象。
- 創(chuàng)建一個新的 HTTP 請求,并指定該 HTTP 請求的方法、URL 及驗證信息。
- 設(shè)置響應(yīng) HTTP 請求狀態(tài)變化的函數(shù)。
- 發(fā)送 HTTP 請求
- 獲取異步調(diào)用返回的數(shù)據(jù)
- 使用 JavaScript 和 DOM 實現(xiàn)局部刷新
get 和 post 請求方式的差異
- get 請求沒有請求主體,使用 xhr.send(null)。
- get 可以通過在請求 URL 上添加請求參數(shù)。
- post 可以通過 xhr.send('name=i&age=10')。
- post 需要設(shè)置請求頭 xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
- get 效率更好(應(yīng)用比較多)。
- get 大小限制約 4K,post則沒有限制。
get 和 post 的區(qū)別,什么時候使用 post 請求
- get:一般用于信息獲取,使用 URL 傳遞參數(shù),對所發(fā)信息的數(shù)量也有限制,一般在 2000 個字符,有的瀏覽器是 8000 個字符。
- 一般用于修改服務(wù)器上的資源,對所發(fā)送的信息沒有限制。
以下情況中,使用post 請求:- 無法使用緩存文件(更新服務(wù)器上的文件或數(shù)據(jù)庫)
- 向服務(wù)器發(fā)送大量數(shù)據(jù)(post 沒有數(shù)據(jù)量限制)
- 發(fā)送包含未知字符的用戶輸入時,post 比 get 更穩(wěn)定也更可靠。
jquery 中的 ajax
- $.ajax({}) 可配置方式發(fā)起 Ajax 請求。
- $.get() 以 get 方式發(fā)起 Ajax 請求。
- $.post() 以 post 方式發(fā)起ajax請求。
- $('form').serialize() 序列化表單(即格式化 key=val&key=val)
- url 接口地址
- type 請求方式
- timeout 請求超時
- dataType 服務(wù)器返回格式
- data 發(fā)送請求數(shù)據(jù)
- beforeSend:function(){} 請求發(fā)起前調(diào)用
- success 成功響應(yīng)后調(diào)用
- error 錯誤響應(yīng)時調(diào)用
- complete 響應(yīng)完成時調(diào)用(包括成功和失敗)
最后
忽然發(fā)現(xiàn)已經(jīng)忘了 ajax 的一些理論基礎(chǔ)方面的知識了... 面試忽然問起,恩,懵住了... 所以學習嘛,還是要時常復(fù)習。