理解AJAX

先參考MDN的什麼是AJAX

AJAX是異步的JavaScript和XML(Asynchronous JavaScript And XML)。簡單點說,就是使用 XMLHttpRequest 對象與服務器通信。 它可以使用JSON,XML,HTML和text文本等格式發送和接收數據。AJAX最吸引人的就是它的“異步”特性,也就是說他可以在不重新刷新頁面的情況下與服務器通信,交換數據,或更新頁面。

使用AJAX的兩個特性

  • 在不重新加載頁面的情況下發送請求給服務器。
  • 接受並使用從服務器發來的數據。

AJAX請求過程是什麼樣的

先看代碼

function request(){
    let httpRequest = new XMLHttpRequest();
    //要在函數閉包內創建XHR變量,避免被其他request相互覆蓋;
    if(!httpRequest){
        alert('Giving up :( Cannot create an XMLHTTP instance');
        return false;
    }

    httpRequest.onreadystatechange = alertContents;
    httpRequest.open('GET', 'test.html');
    httpRequest.send();
}

function alertContents() {
    if (httpRequest.readyState === XMLHttpRequest.DONE) {
      if (httpRequest.status === 200) {
        alert(httpRequest.responseText);
      } else {
        alert('There was a problem with the request.');
      }
    }
  }

創建XMLHttpRequest對象

let httpRequest = new XMLHttpRequest();

什麼是onreadystatechange

只要 readyState 屬性發生變化,就會調用相應的處理函數。

在這個例子中,處理函數爲alertContents。要注意的是,函數名後沒有參數,因爲你把一個引用賦值給了函數,而不是真正的調用了它。下面會講關於這個處理函數的具體實現。

還有onload()

onreadystatechange顧名思義,每次state變化的時候都會調用被給的函數,如果只想在狀態爲完成的時候被調用,可以使用onload來代替。

open() 初始化

  • 不管get還是post,都要先open()。
  • 第一個參數是HTTP請求方法 - 有GET,POST,HEAD以及服務器支持的其他方法。 保證這些方法一定要是大寫字母,否則其他一些瀏覽器(比如FireFox)可能無法處理這個請求。
  • 第二個參數是你要發送的URL。由於安全原因,默認不能調用第三方URL域名。 確保你在頁面中使用的是正確的域名,否則在調用 open() 方法是會有 “權限被拒絕” 錯誤提示。一個容易犯的錯誤是你企圖通過 domain.tld 訪問網站,而不是使用 www.domain.tld。
  • 第三個參數是可選的,用於設置請求是否是異步的。如果設爲 true (默認設置),JavaScript執行會持續,並且在服務器還沒有響應的情況下與頁面進行交互。

send() 發送

上面的就是一個get情景中,用send()的例子

再提供一個post例子

post要設定相應的request header,調用setRequestHeader()

var xhr = new XMLHttpRequest();
xhr.open("POST", '/server', true);

//如果要post就要設定相應的request header
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

xhr.onreadystatechange = function() { //這裏定義onreadystatechange前面已經講過了
    if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
        // 請求完畢,做一些處理
    }
}
xhr.send("foo=bar&lorem=ipsum");//正式發送的send()調用

處理onreadystatechange的函數實現

我們知道會把一個函數賦予xhr.onreadystatechange。那麼這個函數應該做什麼?


首先,函數要檢查請求的狀態。如果狀態的值是 XMLHttpRequest.DONE (對應的值是4),意味着服務器響應收到了並且是沒問題的,然後就可以繼續執行。

if (httpRequest.readyState === XMLHttpRequest.DONE) {
    ...
} else {
   ...
}
readyState對應值
  • 0 UNSENT 還沒open()
  • 1 OPENED 已經open()了
  • 2 HEADERS_RECEIVED 已經send()了
  • 3 LOADING 獲取返回數據中
  • 4 DONE 完成

接下來,檢查HTTP響應的 response code。 可能的響應碼都已經列在表中 W3C響應碼列表。在下面的例子中,我們通過檢查響應碼 200 OK 區別對待成功和不成功的AJAX調用。

if (httpRequest.status === 200) {
   ...
} else {
  ...
}
粗略的響應碼解釋
  • 2XX 成功
  • 3XX 重新導向
  • 4XX 請求有問題
  • 5XX 服務端有問題

一切檢查後,那麼怎麼獲取返回數據?

  • httpRequest.responseText – 服務器以文本字符的形式返回
  • httpRequest.responseXML – 以 XMLDocument 對象方式返回,之後就可以使用JavaScript來處理

那麼經常看到的jquery中的ajax是什麼樣的?

我們平常用jquery的ajax都是傳一個對象,來具體自己想做什麼樣的請求。
那麼實現ajax的時候,也是先要從這傳進來的一個對象裏面找參數。處理完了以後就用這些得到的參數去做請求就可以了。

粗略的實現
function ajax(options){
    if(window.XMLHttpRequest){
        let xhr = new XMLHttpRequest;
    }else{
        let xhr = new ActiveXObject();//IE6 and oler
    }

    //從option獲取一些參數
    let method = options.type || 'GET';
    let dataType = options.dataType || 'application/x-www-form-urlencoded';
    let params = options.data;
    let success = options.success;
    let fail = option.fail;
    ...
    
    //設置onreadystatechange
    xhr.onreadystatechange = function(){
        if(xhr.readyState === 4 && xhr.status === 200){
           //call success
        }else{
            //call fail
        }
    }
    
    //正式進行請求
    if(method == 'GET){
        xhr.open('GET',url + '?' + params,true);
        xhr.send();
    }else if(method == 'POST'){
        xhr.open('POST',url, true);
        xhr.setRequestHeader('Content-Type', dataType);
        xhr.send(params);
    }else{
       ...other method handler
    }
}

當然還可以fetch

Fetch 是瀏覽器提供的原生 AJAX 接口。這裏不做過多介紹。

重點提到的就是fetch請求返回的是一個Promise,所以對獲取數據處理要用then()

一些例子
fetch('/data.json')
.then(res => {
  res.text()       // response body (=> 還是返回Promise,需要再then())
  res.json()       // parse via JSON (=> 還是返回Promise,需要再then())
  res.status       //=> 200
  res.statusText   //=> 'OK'
  res.redirected   //=> false
  res.ok           //=> true
  res.url          //=> 'http://site.com/data.json'
  res.type         //=> 'basic'
                   //   ('cors' 'default' 'error'
                   //    'opaque' 'opaqueredirect')

  res.headers.get('Content-Type')
})

參考信息

MDN 什麼是AJAX?
MDN XMLHttpRequest
阮一峯ES6指南 Promise對象
fetch cheatsheet

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章