400-650-7353
1、簡介
瀏覽器與服務(wù)器之間,采用 HTTP 協(xié)議通信。用戶在瀏覽器地址欄鍵入一個網(wǎng)址,或者通過網(wǎng)頁表單向服務(wù)器提交內(nèi)容,這時瀏覽器就會向服務(wù)器發(fā)出 HTTP 請求。
1999年,微軟公司發(fā)布 IE 瀏覽器5.0版,第一次引入新功能:允許 JavaScript 腳本向服務(wù)器發(fā)起 HTTP 請求。這個功能當時并沒有引起注意,直到2004年的 Gmail 發(fā)布和2005年的 Google Map 發(fā)布,才引起廣泛重視。
2005年2月,AJAX 這個詞第一次正式提出,它是 Asynchronous JavaScript and XML 的縮寫,指的是通過 JavaScript 的異步通信,從服務(wù)器獲取 XML 文檔從中提取數(shù)據(jù),再更新當前網(wǎng)頁的對應(yīng)部分,而不用刷新整個網(wǎng)頁。后來,AJAX 這個詞就成為 JavaScript 腳本發(fā)起 HTTP 通信的代名詞。也就是說,只要用腳本發(fā)起通信,就可以叫做 AJAX 通信。W3C 也在2006年發(fā)布了它的國際標準。
AJAX發(fā)起請求,具體包括以下幾個步驟:
1.創(chuàng)建 XMLHttpRequest 實例
2.發(fā)出 HTTP 請求
3.接收服務(wù)器傳回的數(shù)據(jù)
4.更新網(wǎng)頁數(shù)據(jù)
概括起來,就是一句話,AJAX 通過原生的XMLHttpRequest對象發(fā)出 HTTP 請求,得到服務(wù)器返回的數(shù)據(jù)后,再進行處理,F(xiàn)在,服務(wù)器返回的都是 JSON 格式的數(shù)據(jù),XML 格式已經(jīng)過時了,但是 AJAX 這個名字已經(jīng)成了一個通用名詞,字面含義已經(jīng)消失了。
2、主要接口
XMLHttpRequest對象是AJAX的主要接口,它本身是一個構(gòu)造函數(shù),可以使用new命令生成實例,它沒有任何參數(shù)。
- var xhr = new XMLHttpRequest();
有了xhr實例,就可以調(diào)用它下面的open方法。
- xhr.open('GET', '請求url地址', true);
然后,指定回調(diào)函數(shù),監(jiān)聽通信狀態(tài)的變化。一旦xhr的readyState屬性狀態(tài)發(fā)生變化,就會調(diào)用該函數(shù)。
- xhr.onreadystatechange = function (){ }
最后調(diào)用send(),實際發(fā)出 HTTP 請求。
- xhr.send();
拿到服務(wù)器返回的數(shù)據(jù)后,AJAX 不會刷新整個網(wǎng)頁,而是只更新網(wǎng)頁里面的相關(guān)部分,從而不打斷用戶正在做的事情。
當然,AJAX只能向同源網(wǎng)址(協(xié)議、域名、端口都相同)發(fā)出 HTTP 請求,如果發(fā)出跨域請求,就會報錯。
- var xhr = new XMLHttpRequest();
- xhr.open('GET', '請求url地址', true);
- xhr.onreadystatechange = function () {
- if (xhr.readyState === 4) {
- if (xhr.status === 200) {
- console.log(xhr.responseText); // 取得數(shù)據(jù)
- } else {
- console.error(xhr.statusText); // 提示信息
- }
- }
- };
- xhr.send();
3、XMLHttpRequest的實例屬性
- var xhr = new XMLHttpRequest();
我們下面討論的都是XMLHttpRequest下面的屬性,以xhr代指實例。
1、xhr.readyState
表示實例對象的當前狀態(tài)。該屬性只讀。
AJAX通信的過程中,會有5個階段,分別用0--4的數(shù)字代表。xhr.readyState返回數(shù)字,代表當前通信到了哪個階段。
• 0:表示 XMLHttpRequest 實例已經(jīng)生成,但是實例的open()方法還沒有被調(diào)用。
• 1:表示open()方法已經(jīng)調(diào)用,但是實例的send()方法還沒有調(diào)用,仍然可以使用實例的setRequestHeader()方法,設(shè)定 HTTP 請求的頭信息。
• 2:表示實例的send()方法已經(jīng)調(diào)用,并且服務(wù)器返回的頭信息和狀態(tài)碼已經(jīng)收到。
• 3:表示正在接收服務(wù)器傳來的數(shù)據(jù)體(body 部分)。這時,如果實例的responseType屬性等于text或者空字符串,responseText屬性就會包含已經(jīng)收到的部分信息。
• 4:表示服務(wù)器返回的數(shù)據(jù)已經(jīng)完全接收,或者本次接收已經(jīng)失敗。
通信過程中,只要實例的狀態(tài)發(fā)生變化,它的xhr.readyState屬性值就會發(fā)生變化,這個值每一次變化,都會觸發(fā)onreadystatechange事件。而通常情況下,我們關(guān)心的是狀態(tài)為4的時候,代表發(fā)起的HTTP請求已經(jīng)成功。
2、xhr.status 和 xhr.statusText
status屬性返回一個整數(shù),表示服務(wù)器回應(yīng)的 HTTP 狀態(tài)碼。一般來說,如果通信成功的話,這個狀態(tài)碼是200;如果服務(wù)器沒有返回狀態(tài)碼,那么這個屬性默認是200。該屬性只讀。
• 200, OK,訪問正常
• 301, Moved Permanently,永久移動
• 302, Move temporarily,暫時移動
• 304, Not Modified,未修改
• 307, Temporary Redirect,暫時重定向
• 401, Unauthorized,未授權(quán)
• 403, Forbidden,禁止訪問
• 404, Not Found,未發(fā)現(xiàn)指定網(wǎng)址
• 500, Internal Server Error,服務(wù)器發(fā)生錯誤
只有2xx和304的狀態(tài)碼,表示服務(wù)器返回是正常狀態(tài)。
statusText屬性返回一個字符串,表示服務(wù)器發(fā)送的狀態(tài)提示。不同于status屬性,該屬性包含整個狀態(tài)信息,比如“OK”和“Not Found”。如果服務(wù)器沒有返回狀態(tài)提示,該屬性的值默認為”“OK”。該屬性為只讀屬性。
- var xhr = new XMLHttpRequest();
- xhr.open('GET', '請求url地址', true);
- xhr.onreadystatechange = function () {
- if (xhr.readyState === 4) {
- if ((xhr.status >= 200 && xhr.status < 300) || (xhr.status ===
- 304)) {
- // 處理服務(wù)器的返回數(shù)據(jù)
- } else {
- // 出錯
- }
- }
- };
- xhr.send();
3、xhr.responseType
該屬性是一個字符串,表示希望服務(wù)器返回數(shù)據(jù)的類型。
這個屬性是可寫的,可以在調(diào)用open()方法之后、調(diào)用send()方法之前,設(shè)置這個屬性的值,告訴服務(wù)器返回指定類型的數(shù)據(jù)。如果responseType設(shè)為空字符串,就等同于默認值text。
responseType屬性可以是:
• "arraybuffer":ArrayBuffer 對象,表示服務(wù)器返回二進制數(shù)組。
• "blob":Blob 對象,表示服務(wù)器返回二進制對象。
• "document":Document 對象,表示服務(wù)器返回一個文檔對象。
• "json":JSON 對象。
• "text":字符串,表示服務(wù)器返回文本數(shù)據(jù)。
• ""(空字符串):等同于"text"。
text類型適合大多數(shù)情況,而且直接處理文本也比較方便。
document類型適合返回 HTML / XML 文檔的情況
blob類型適合讀取二進制數(shù)據(jù),比如圖片文件。
json,瀏覽器就會自動對返回數(shù)據(jù)調(diào)用JSON.parse()方法。也就是說,從xhr.response屬性(注意,不是xhr.responseText屬性)得到的不是文本,而是一個 JSON 對象。
4、xhr.response
該屬性表示服務(wù)器返回的數(shù)據(jù)體(即 HTTP 回應(yīng)的 body 部分),它可能是任何數(shù)據(jù)類型。具體的類型由xhr.responseType屬性決定。該屬性只讀。如果本次請求沒有成功或者數(shù)據(jù)不完整,該屬性等于null
- var xhr = new XMLHttpRequest();
- xhr.open('GET', '請求url地址', true);
- xhr.onreadystatechange = function () {
- // readyState狀態(tài)為4,代表請求完成
- if(xhr.readyState === 4){
- // 返回的數(shù)據(jù)
- console.log(xhr.response);
- }
- };
- xhr.send();
5、xhr.responseText
該屬性返回從服務(wù)器接收到的字符串,該屬性為只讀。只有 HTTP 請求完成接收以后,該屬性才會包含完整的數(shù)據(jù)。
- var xhr = new XMLHttpRequest();
- xhr.open('GET', '請求url地址', true);
- xhr.responseType = 'text';
- xhr.onreadystatechange = function () {
- if (xhr.readyState === 4 && xhr.status === 200) {
- // 請求成功的數(shù)據(jù)
- console.log(xhr.responseText);
- }
- };
- xhr.send();
6、xhr.timeout
設(shè)置超時,該屬性接收一個整數(shù),表示多少毫秒后,如果請求仍然沒有得到結(jié)果,就會自動終止。如果該屬性等于0,就表示沒有時間限制。
- var xhr = new XMLHttpRequest();
- xhr.open('GET', '請求url地址', true);
- xhr.onreadystatechange = function () {
- // readyState狀態(tài)為4,代表請求完成
- if (xhr.readyState === 4) {
- console.log(xhr.response);
- }
- };
- // 指定 10 秒鐘超時
- xhr.timeout = 10 * 1000;
- xhr.send();
7、xhr.upload
XMLHttpRequest 不僅可以發(fā)送請求,還可以發(fā)送文件,這就是 AJAX 文件上傳。發(fā)送文件以后,通過xhr.upload屬性可以得到一個對象,通過觀察這個對象,可以得知上傳的進展。主要方法就是監(jiān)聽這個對象的各種事件:loadstart、loadend、load、abort、error、progress、timeout。文件上傳時,對upload屬性指定progress事件的監(jiān)聽函數(shù),即可獲得上傳的進度。
- var progressBar =document.querySelector('progress'); //展示進度的元素
- var xhr = new XMLHttpRequest();
- xhr.open('POST', '請求url地址', true);
- xhr.upload.onprogress = function (e) {
- if (e.lengthComputable) {
- progressBar.innerText = (e.loaded / e.total) * 100;
- } else {
- console.log('無法計算進展');
- }
- };
- xhr.send(上傳的文件對象);
4、XMLHttpRequest的實例方法
- var xhr = new XMLHttpRequest();
我們下面討論的都是XMLHttpRequest下面的方法,以xhr代指實例。
1、xhr.open()
該方法用于指定 HTTP 請求的參數(shù),它一共可以接受五個參數(shù)。
- xhr.open(method, url, async, user, password);
• method:表示 HTTP 動詞方式,比如GET、POST、PUT、DELETE、HEAD等。
• url: 表示請求發(fā)送目標 URL。
• async: 布爾值,表示請求是否為異步,默認為true。如果設(shè)為false,則send()方法只有等到收到服務(wù)器返回了結(jié)果,才會進行下一步操作。該參數(shù)可選。
• user:表示用于認證的用戶名,默認為空字符串。該參數(shù)可選。
• password:表示用于認證的密碼,默認為空字符串。該參數(shù)可選。
2、xhr.send()
該方法用于實際發(fā)出 HTTP 請求。它的參數(shù)是可選的,如果不帶參數(shù),就表示 HTTP 請求只包含頭信息,也就是只有一個 URL,典型例子就是 GET 請求;如果帶有參數(shù),就表示除了頭信息,還帶有包含具體數(shù)據(jù)的信息體,典型例子就是 POST 請求。
注意:所有 XMLHttpRequest 的監(jiān)聽事件,都必須在send()方法調(diào)用之前設(shè)定。
3、xhr.setRequestHeader()
該方法用于設(shè)置瀏覽器發(fā)送的 HTTP 請求的頭信息。該方法必須在open()之后、send()之前調(diào)用。
該方法接受兩個參數(shù)。第一個參數(shù)是字符串,表示頭信息的字段名,第二個參數(shù)是字段值。
- xhr.setRequestHeader('Content-Type', 'multipart/form-data');
4、xhr.abort()
該方法用來終止已經(jīng)發(fā)出的 HTTP 請求。調(diào)用這個方法以后,readyState屬性變?yōu)?,status屬性變?yōu)?。
- var xhr = new XMLHttpRequest();
- xhr.open('GET', '請求url地址', true);
- setTimeout(function () {
- if (xhr) {
- xhr.abort();
- xhr = null;
- }
- }, 5000);
5、XMLHttpRequest實例的事件
1、xhr.onreadyStateChange 事件
該屬性指向一個監(jiān)聽函數(shù),只要xhr.readyState的屬性發(fā)生變化,就會觸發(fā)該函數(shù)。
- var xhr = new XMLHttpRequest();
- xhr.open('GET', '請求url地址', true);
- xhr.onreadystatechange = function () { };
- xhr.send();
2、xhr.onprogress 事件
上傳文件時,XMLHTTPRequest 實例對象本身和實例的upload屬性,都有一個progress事件,會不斷返回上傳的進度。
- var xhr = new XMLHttpRequest();
- xhr.open();
- xhr.onprogress = function (e) {
- if (e.lengthComputable) {
- var percentComplete = e.loaded / e.total;
- } else {
- console.log('無法計算進展');
- }
- }
3、xhr.onload 事件、xhr.onerror 事件、xhr.onabort 事件
load 事件表示服務(wù)器傳來的數(shù)據(jù)接收完畢,error 事件表示請求出錯,abort 事件表示請求被中斷(比如用戶取消請求)。
- var xhr = new XMLHttpRequest();xhr.open();
- function transferComplete() {
- console.log('數(shù)據(jù)接收完畢');
- }
- function transferFailed() {
- console.log('數(shù)據(jù)接收出錯');
- }
- function transferCanceled() {
- console.log('用戶取消接收');
- }
- xhr.addEventListener('load', transferComplete);
- xhr.addEventListener('error', transferFailed);
- xhr.addEventListener('abort', transferCanceled);
4、xhr.onloadend 事件
abort、load和error這三個事件,會伴隨一個loadend事件,表示請求結(jié)束,但不知道其是否成功。
- var xhr = new XMLHttpRequest();
- xhr.open();
- function loadEnd(e) {
- console.log('請求結(jié)束,狀態(tài)未知');
- }
- xhr.addEventListener('loadend', loadEnd);
5、xhr.ontimeout 事件
服務(wù)器超過指定時間還沒有返回結(jié)果,就會觸發(fā) timeout 事件。