什麼是Ajax(Ajax的來歷、執行原理、優缺點及其它)

weixin_34138377發表於2017-10-31

大家好,我是IT修真院深圳分院第3期的學員,一枚正直純潔善良的前端程式設計師,今天給大家分享一下,修真院官網前端工程師深度思考中的知識點——什麼是Ajax


一.背景介紹


Ajax的來歷

套用一句不恰當的話,Ajax就是中間商(並不賺取差價),換一個專業點的說話,現在它就是指令碼發起HTTP通訊的代名詞

具體什麼是Ajax呢?我們在說這個問題之前,需要思考一個問題:當我們上網的時候,我們到底在上什麼?

大部分人都是在上瀏覽器。

當我們在瀏覽器位址列鍵入一個網址,或者通過網頁表單向伺服器提交內容的時候,我們就開始與瀏覽器進行互動。而瀏覽器在這個時候,開始與伺服器進行互動。

傳統的Web應用互動由使用者觸發一個HTTP請求到伺服器,伺服器對其進行處理後再返回一個新的HTML頁到客戶端。

每當伺服器處理客戶端提交的請求時,客戶都只能空閒等待,並且哪怕只是一次很小的互動、只需從伺服器端得到很簡單的一個資料

都要返回一個完整的HTML頁,而客戶端每次都要浪費時間和頻寬去重新讀取整個頁面。

1999年,微軟公司釋出IE瀏覽器5.0版,第一次引入新功能:允許JavaScript指令碼向伺服器發起HTTP請求。這個功能當時並沒有引起注意,為什麼?

實際上,人們一直在尋求改善傳統的web應用互動方式。1999年以前,JS可以通過Java applet或Flash電影等中間層向伺服器傳送請求。

在Ajax被提出之前,這種技術就已經存在很長時間了,那時候人們通常將這種技術叫做遠端指令碼(remote scripting)

Ajax技術的核心是XMLHttpRequest(簡稱XHR),這是由微軟首先引入的一個特性,最早應用在它的IE5瀏覽器上。

在IE5中,XHR物件是通過MSXML庫中的一個ActiveX物件實現的,而IE7+及其他標準瀏覽器都支援原生的XHR物件

在XHR出現之前,Ajax式的通訊必須藉助一些hack首選來實現,大多數使用隱藏或內嵌的框架來。

在XHR出現之後,XHR為向瀏覽器傳送請求和解析伺服器響應提供了流暢的介面。

隨著XHR、JS等各項技術應用得越來越廣泛,2005年,依賴XHR的Ajax技術被提出



瀏覽器與伺服器互動圖例

7995515-e0b1d1eba72c93e7.png

7995515-bace42f0161c959d.png


二.知識剖析

1、執行機制

2、程式碼示例

3、優缺點

1、執行機制

先看一下Ajax的英文翻譯

AJAX stands for Asynchronous JavaScript and XML.

AJAX is a new technique for creating better, faster, and more interactive web applications with the help of XML, HTML, CSS, and Java Script.

AJAX is based on the following open standards:

Browser-based presentation using HTML and Cascading Style Sheets (CSS).

Data is stored in XML format and fetched from the server.

Behind-the-scenes data fetches using XMLHttpRequest objects in the browser.

JavaScript to make everything happen.

從上可以看出Ajax依賴CSS/HTML/Javascript,而其中最核心的依賴是瀏覽器提供的XMLHttpRequest簡稱(XHR)物件,是這個物件使得瀏覽器可以發出HTTP請求與接收HTTP

響應。

W3C形象的稱XHR物件是開發者的夢想

Ajax的工作原理相當於在使用者和伺服器之間加了—箇中間層(AJAX引擎),使使用者操作與伺服器響應非同步化。

並不是所有的使用者請求都提交給伺服器,像—些資料驗證和資料處理等都交給Ajax引擎自己來做, 只有確定需要從伺服器讀取新資料時再由Ajax引擎代為向伺服器提交請求。

Ajax就這樣集齊CSS、JavaScript、XMLHTTPRequest、DOM物件四神獸,通過XmlHttpRequest

物件來向伺服器發非同步請求,從伺服器獲得資料,然後用JavaScript來操作DOM、改變CSS,更新頁面。

Ajax重要影響是使WEB中的介面與應用分離(也可以說是資料與呈現分離),而在以前兩者是沒有清晰的界限的。

資料與呈現分離的分離,有利於分工合作、減少非技術人員對頁面的修改造成的WEB應用程式錯誤、提高效率、也更加適用於現在的釋出系統。

也可以把以前的一些伺服器負擔的工作轉嫁到客戶端,利於客戶端閒置的處理能力來處理。

2、程式碼示例

一段使用XMLHttpRequest傳送Ajax請求的簡單示例程式碼。


function sendAjax() {

//構造表單資料

var formData = new FormData();

formData.append('username', 'johndoe');

formData.append('id', 123456);

//建立xhr物件

var xhr = new XMLHttpRequest();

//設定xhr請求的超時時間

xhr.timeout = 3000;

//設定響應返回的資料格式

xhr.responseType = "text";

//建立一個 post 請求,採用非同步

xhr.open('POST', '/server', true);

//註冊相關事件回撥處理函式

xhr.onload = function(e) {

if(this.status == 200||this.status == 304){

alert(this.responseText);

}

};

xhr.ontimeout = function(e) { ... };

xhr.onerror = function(e) { ... };

xhr.upload.onprogress = function(e) { ... };

//傳送資料

xhr.send(formData);

}

上面是一個使用xhr傳送表單資料的示例,整個流程可以參考註釋。




3、優缺點


(1).AJAX的優點

<1>.無重新整理更新資料。AJAX最大優點就是能在不重新整理整個頁面的前提下與伺服器通訊維護資料。這使得Web應用程式更為迅捷地響應使用者互動,並避免了在網路上傳送那些沒有改變的資訊,減少使用者等待時間,帶來非常好的使用者體驗。

<2>.非同步與伺服器通訊。

AJAX使用非同步方式與伺服器通訊,不需要打斷使用者的操作,具有更加迅速的響應能力。優化了Browser和Server之間的溝通,減少不必要的資料傳輸、時間及降低網路上資料流量。

<3>.前端和後端負載平衡。

AJAX可以把以前一些伺服器負擔的工作轉嫁到客戶端,利用客戶端閒置的能力來處理,減輕伺服器和頻寬的負擔,節約空間和寬頻租用成本。並且減輕伺服器的負擔,AJAX的原則是“按需取資料”,可以最大程度的減少冗餘請求和響應對伺服器造成的負擔,提升站點效能

<4>.基於標準被廣泛支援。

AJAX基於標準化的並被廣泛支援的技術,不需要下載瀏覽器外掛或者小程式,但需要客戶允許JavaScript在瀏覽器上執行。隨著Ajax的成熟,一些簡化Ajax使用方法的程式庫也相繼問世。同樣,也出現了另一種輔助程式設計的技術,為那些不支援JavaScript的使用者提供替代功能。

<5>.介面與應用分離。

Ajax使WEB中的介面與應用分離(也可以說是資料與呈現分離),有利於分工合作、減少非技術人員對頁面的修改造成的WEB應用程式錯誤、提高效率、也更加適用於現在的釋出系統。

(2).AJAX的缺點

<1>.AJAX幹掉了Back和History功能,即對瀏覽器機制的破壞。

在動態更新頁面的情況下,使用者無法回到前一個頁面狀態,因為瀏覽器僅能記憶歷史記錄中的靜態頁面。一個被完整讀入的頁面與一個已經被動態修改過的頁面之間的差別非常微妙;使用者通常會希望單擊後退按鈕能夠取消他們的前一次操作,但是在Ajax應用程式中,這將無法實現。

<2>.AJAX的安全問題。

AJAX技術給使用者帶來很好的使用者體驗的同時也對IT企業帶來了新的安全威脅,Ajax技術就如同對企業資料建立了一個直接通道。這使得開發者在不經意間會暴露比以前更多的資料和伺服器邏輯。Ajax的邏輯可以對客戶端的安全掃描技術隱藏起來,允許黑客從遠端伺服器上建立新的攻擊。還有Ajax也難以避免一些已知的安全弱點,諸如跨站點腳步攻擊、SQL隱碼攻擊和基於Credentials的安全漏洞等等。

<3>.對搜尋引擎支援較弱。

對搜尋引擎的支援比較弱。如果使用不當,AJAX會增大網路資料的流量,從而降低整個系統的效能。

<4>.破壞程式的異常處理機制。

<5>.違背URL和資源定位的初衷。

例如,我給你一個URL地址,如果採用了Ajax技術,也許你在該URL地址下面看到的和我在這個URL地址下看到的內容是不同的。這個和資源定位的初衷是相背離的。

<6>.AJAX不能很好支援移動裝置。

一些手持裝置(如手機、PDA等)現在還不能很好的支援Ajax,比如說我們在手機的瀏覽器上開啟採用Ajax技術的網站時,它目前是不支援的。

<7>.客戶端過肥,太多客戶端程式碼造成開發上的成本。

編寫複雜、容易出錯 ;冗餘程式碼比較多(層層包含js檔案是AJAX的通病,再加上以往的很多服務端程式碼現在放到了客戶端);破壞了Web的原有標準。

需要注意的是:

Ajax開發時,網路延遲——即使用者發出請求到伺服器發出響應之間的間隔——需要慎重考慮。不給予使用者明確的回應,沒有恰當的預讀資料,或者對XMLHttpRequest的不恰當處理,都會使使用者感到延遲,這是使用者不希望看到的,也是他們無法理解的。通常的解決方案是,使用一個視覺化的元件來告訴使用者系統正在進行後臺操作並且正在讀取資料和內容。






3.常見問題

1、IE瀏覽器下面的快取問題

2、跨域問題

3、Ajax亂碼問題

4、使用post提交的時候需要設定content-type為"application/x-www-form-urlencoded"

5、Ajax物件屬性的大小寫問題

6、Ajax狀態為0的問題



下面一一講解常見問題出現的原因和解決辦法






四.解決方案

1. 快取問題



在IE瀏覽器下面使用get請求時,如果第一次請求了資料之後IE會自動快取資料,如果下一次再傳送同樣的

請求的時候瀏覽器會自動先去找快取顯示出來,所以如果請求的資料有變化的時候,這裡是看不到變化的。

解決辦法:

xhr.open("get","xxxx.aspx?_dc="+new Date().getTime(),true);

就是在請求的後面 加上時間戳或是隨機數,讓url變成唯一,或者是,改成post請求。

(get和post請求的區別可參見 淺談HTTP中Get與Post的區別

2. 跨域問題

這是我們目前見到的最多的,也是最熟悉的一個問題。本地上面直接採用Nginx跨域實現。在伺服器上實現跨域,可以通過後端達成,可參考

href="http://www.cnblogs.com/fanyx/p/5775939.html">跨域有幾種處理方式?

注意 Nginx跨域可以同時配置多個介面的,就是多寫幾個location就好了,然後location後面帶的引數不一樣就可以了。

3. Ajax亂碼問題

亂碼問題雖然我們目前遇到的不多,但是也屬於比較常見的一個問題了。出現的主要原因就是編碼不一致導致的。

如果出現亂碼問題了,首先檢查一下meta宣告的charset要和請求的頁面返回的charset一致。response.charset="gb2312 or utf-8"

4. 使用post提交的時候需要進行的設定

content-Type: application/x-www-form-urlencoded;

//jQuery中,

content-Type: application/x-www-form-urlencoded;charset=utf-8;

//AngularJS中$http

content-Type: application/json; charset=utf-8;

//使用原生Ajax需要在open以後才能使用xhr.setRequestHeader()方法,否則出錯

xhr.open("post","xxxx.aspx",true);

xhr.setRequestHeader("content-type","application/x-www-form-urlencoded")

//用原生寫時必須在open()方法之後send()方法之前呼叫

5. Ajax物件屬性的大小寫問題

有些瀏覽器比如火狐,對大小寫是敏感的,if (xhr.readystate==4)這種寫法,

在IE下是成立的,但是在Firefox下就行不通了,因為IE不區分大小寫,Firefox是區分大小的。標準寫法為if (xhr.readyState==4),同理還有屬性

responseText,responseXML。習慣採用駝峰形式的寫法可以避免這個問題。

6. Ajax狀態0的問題

有時候在測試Ajax程式碼的時候加了 xhr.status==200的判斷後,一直不執行xhr.status==200的程式碼,

這個就需要注意了。xhr.status==200是要通過伺服器確認後來返回的,在伺服器頁面沒有發生錯誤或者轉向時才返回200狀態的,

此狀態和你通過瀏覽器訪問頁面時伺服器定義的狀態一致。直接拖進瀏覽器瀏覽結果或者雙擊執行html頁面的,未發生錯誤時,此時的xhr.status是0,不是200。

1. 快取問題

在IE瀏覽器下面使用get請求時,如果第一次請求了資料之後IE會自動快取資料,如果下一次再傳送同樣的

請求的時候瀏覽器會自動先去找快取顯示出來,所以如果請求的資料有變化的時候,這裡是看不到變化的。

解決辦法:

xhr.open("get","xxxx.aspx?_dc="+new Date().getTime(),true);

就是在請求的後面 加上時間戳或是隨機數,讓url變成唯一,或者是,改成post請求。

(get和post請求的區別可參見淺談HTTP中Get與Post的區別)

2. 跨域問題

這是我們目前見到的最多的,也是最熟悉的一個問題。本地上面直接採用Nginx跨域實現。在伺服器上實現跨域,可以通過後端達成,可參考

href="http://www.cnblogs.com/fanyx/p/5775939.html">跨域有幾種處理方式?

注意 Nginx跨域可以同時配置多個介面的,就是多寫幾個location就好了,然後location後面帶的引數不一樣就可以了。

3. Ajax亂碼問題

亂碼問題雖然我們目前遇到的不多,但是也屬於比較常見的一個問題了。出現的主要原因就是編碼不一致導致的。

如果出現亂碼問題了,首先檢查一下meta宣告的charset要和請求的頁面返回的charset一致。response.charset="gb2312 or utf-8"

4. 使用post提交的時候需要進行的設定

content-Type: application/x-www-form-urlencoded;

//jQuery中,

content-Type: application/x-www-form-urlencoded;charset=utf-8;

//AngularJS中$http

content-Type: application/json; charset=utf-8;

//使用原生Ajax需要在open以後才能使用xhr.setRequestHeader()方法,否則出錯

xhr.open("post","xxxx.aspx",true);

xhr.setRequestHeader("content-type","application/x-www-form-urlencoded")

//用原生寫時必須在open()方法之後send()方法之前呼叫

5. Ajax物件屬性的大小寫問題

有些瀏覽器比如火狐,對大小寫是敏感的,if (xhr.readystate==4)這種寫法,

在IE下是成立的,但是在Firefox下就行不通了,因為IE不區分大小寫,Firefox是區分大小的。標準寫法為if (xhr.readyState==4),同理還有屬性

responseText,responseXML。習慣採用駝峰形式的寫法可以避免這個問題。

6. Ajax狀態0的問題

有時候在測試Ajax程式碼的時候加了 xhr.status==200的判斷後,一直不執行xhr.status==200的程式碼,

這個就需要注意了。xhr.status==200是要通過伺服器確認後來返回的,在伺服器頁面沒有發生錯誤或者轉向時才返回200狀態的,

此狀態和你通過瀏覽器訪問頁面時伺服器定義的狀態一致。直接拖進瀏覽器瀏覽結果或者雙擊執行html頁面的,未發生錯誤時,此時的xhr.status是0,不是200。




5.編碼實戰

jQuery方法

$.ajax({

url:"student-ajax/student",

type:"POST",

dataType:"json",

data:{

name:$("#names").val(),

qq:$("#QQs").val(),

},

success:function(data){

console.log(data);

if(data.code === 200){

alert($("#names").val() + "學員資訊" +data.message);

}else{

alert(data.message);

}

},

error:function(data){

console.log(data);

alert("新增失敗");

}

});

}) ;

AngularJS方法

$http({

method:'get',

url:('/a/a/all/document?type=1&page='+$scope.page),

headers:{'Content-Type':'application/x-www-form-urlencoded'}

})

.success(function (response) {

console.log(response.total);

console.log(response);

// if (response.message === "查詢成功") {

$scope.userList = response.data;

$scope.userTotal = response.total;

$scope.page=response.page;

// console.log($scope.userList.total);

});

Javascript原生方法

var request = new XMLHttpRequest(); // 新建XMLHttpRequest物件;

request.onreadystatechange = function () { // 狀態發生變化時,函式被回撥;

if (request.readyState === 4) { // 成功完成

// 判斷響應結果:

if (request.status === 200) {

// 成功,通過responseText拿到響應的文字:

return success(request.responseText);

} else {

// 失敗,根據響應碼判斷失敗原因:

return fail(request.status);

}

} else {

// HTTP請求還在繼續...

}

}

// 傳送請求:

request.open("POST","/skill-ajax/a/login",true);

request.setRequestHeader("Content-type","application/x-www-form-urlencoded");

request.send();

alert('請求已傳送,請等待響應...');

// readyState值說明

// 0,初始化,XHR物件已經建立,還未執行open

// 1,載入,已經呼叫open方法,但是還沒傳送請求

// 2,載入完成,請求已經傳送完成

// 3,互動,可以接收到部分資料

// status值說明

// 200:成功

// 404:沒有發現檔案、查詢或URl

// 500:伺服器產生內部錯誤



原生的講解

(1)

在使用xhr物件傳送請求和處理請求響應之前,必須先用js語言建立一個xhr物件。由於xhr物件當前還不是w3c標準,所以才有多種方式進行建立以解決相容性問題。具體建立方式如下:

var xmlhttp;

if (window.XMLHttpRequest)

{// code for IE7+, Firefox, Chrome, Opera, Safari

xmlhttp=new XMLHttpRequest();

}

else

{// code for IE6, IE5

xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");

}

(2) 向伺服器傳送請求

(a) open(method,url,async)

規定請求的型別、URL 以及是否非同步處理請求。

method:請求的型別;GET 或 POST

url:檔案在伺服器上的位置

async:true(非同步)或 false(同步)

(b)send(string)

將請求傳送到伺服器。

string:僅用於 POST 請求



6.擴充套件思考


AngularJS請求的時候,success()和then()方法的區別?

$http({

url:'data.json',

method:'GET'

}).success(function(data,header,config,status){

//code goes here

}).error(function(data,header,config,status) {

//code goes here

});

var promise = $http({

url:'data.json',

method:'GET'

});

promise.then(function(resp) {

//resp是一個響應物件

}, function() {

//帶有錯誤資訊的resp

})

要將區別先弄清$http服務,它是對原生XMLHttpRequest物件的簡單封裝,是隻能接受一個引數的方法,這個方法會返回一個promise物件,具有sccess和error兩個方法。當然,我們也可以在響應返回時用then方法來處理,會得到一個特殊的引數,代表了物件的成功或失敗資訊,或者可以使用success和error回撥代替。

這樣就很明晰了,then方法和success方法的主要區別就是,then方法會接受到完整的響應物件,資訊更為全面,而success則會對響應物件進行析構,使用起來更為方便。



7.參考文獻


參考一:什麼是跨域

參考二:AngularJS中then和success的區別

參考三:Ajax常見問題

參考四:你真的會使用XMLHttpRequest嗎?

參考五:AJAX工作原理及其優缺點

參考六:深入理解ajax系列第一篇——XHR物件

參考七:XMLHttpRequest 物件


8.更多討論


題外話,沒有ajax的時候,怎樣提高使用者的體驗?


PPT連線:

PPT

視訊連結


什麼是Ajax(Ajax的來歷、執行原理、優缺點及其它)_騰訊視訊


如果這篇文章對你有幫助,並且使你對修真院免費線上學習感興趣,可以通過我的連結註冊成員會,這會使我得到學分(兌換學時)延長學習時間:

邀請連結:http://www.jnshu.com/login/1/13374512

邀請碼:13374512

相關文章