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