首頁 > 軟體

AJAX原理以及axios、fetch區別範例詳解

2022-04-08 13:01:26

AJAX原理

  • Ajax的原理簡單來說是在使用者和伺服器之間加了—箇中間層(AJAX引擎),通過XmlHttpRequest物件來向伺服器發非同步請求,從伺服器獲得資料,然後用javascript來操作DOM而更新頁面。使使用者操作與伺服器響應非同步化。
  • Ajax的過程只涉及JavaScript、XMLHttpRequest和DOM。XMLHttpRequest是ajax的核心機制

XMLHttpRequest(XHR)物件用於與伺服器互動。通過 XMLHttpRequest 可以在不重新整理頁面的情況下請求特定 URL,獲取資料。這允許網頁在不影響使用者操作的情況下,更新頁面的區域性內容。XMLHttpRequest 可以用於獲取任何型別的資料,而不僅僅是 XML。甚至支援 HTTP以外的協定(包括 file:// 和 FTP),儘管可能受到更多出於安全等原因的限制。

/** 1. 建立Ajax物件 **/
var xhr = window.XMLHttpRequest?new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP');// 相容IE6及以下版本
/** 2. 設定 Ajax請求 **/
xhr.open('get', url, true)
/** 3. 傳送請求 **/
xhr.send(null); // 嚴謹寫法
/** 4. 監聽請求,接受響應 **/
xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
        if(xhr.status == 200){
            success(xhr.responseText);
        } else { 
            /** false **/
            fail && fail(xhr.status);
        }
    }
}
  • onreadystatechange:當 readyState 屬性發生變化時,呼叫的事件處理常式

  • readyState:

    狀態描述
    0UNSENT代理被建立,但尚未呼叫 open() 方法。
    1OPENEDopen() 方法已經被呼叫。
    2HEADERS_RECEIVEDsend() 方法已經被呼叫,並且頭部和狀態已經可獲得。
    3LOADING下載中; responseText 屬性已經包含部分資料。
    4DONE下載操作已完成。
  • response:返回的包含整個響應實體

  • responseText:返回一個DOMString,該 DOMString 包含對請求的響應,如果請求未成功或尚未傳送,則返回 null。

  • responseType:一個用於定義響應型別的列舉值(enumerated value)。

    型別解釋
    “ ”空的 responseType 字串與預設型別 "text" 相同。
    "arraybuffer"response 是一個包含二進位制資料的 JavaScript ArrayBuffer
    "blob"response 是一個包含二進位制資料的 Blob 物件。
    "document"response 是一個 HTMLDocument或XMLDocument
    "json"response是通過將接收到的資料內容解析為JSON的JS物件
    "text"response 是 DOMString 物件中的文字。
    "ms-stream"response是流式下載的一部分;此響應型別僅允許用於下載請求,並且僅受 Internet Explorer 支援。
  • status:返回一個無符號短整型(unsigned short)數位,代表請求的響應狀態。

    var xhr = new XMLHttpRequest();
    console.log('UNSENT', xhr.status);
    
    xhr.open('GET', '/server', true);
    console.log('OPENED', xhr.status);
    
    xhr.onprogress = function () {
      console.log('LOADING', xhr.status);
    };
    
    xhr.onload = function () {
      console.log('DONE', xhr.status);
    };
    
    xhr.send(null);
    
    /**
     * 輸出如下:
     *
     * UNSENT(未傳送) 0
     * OPENED(已開啟) 0
     * LOADING(載入中) 200
     * DONE(完成) 200
     */
  • withCredentials:一個布林值,用來指定跨域 Access-Control 請求是否應當帶有授權資訊,如 cookie 或授權 header 頭。xhr.withCredentials=true

  • upload:代表上傳進度

其他更多XMLHttpRequest相關api

ajax 有那些優缺點?

  • 優點:

    • 通過非同步模式,提升了使用者體驗.
    • 優化了瀏覽器和伺服器之間的傳輸,減少不必要的資料往返,減少了頻寬佔用.
    • Ajax在使用者端執行,承擔了一部分本來由伺服器承擔的工作,減少了大使用者量下的伺服器負載。
    • Ajax可以實現動態不重新整理(區域性重新整理)
  • 缺點:

    • 安全問題 AJAX暴露了與伺服器互動的細節。
    • 對搜尋引擎的支援比較弱。
    • 不容易偵錯。

Promise封裝Ajax

promise 封裝實現:

// promise 封裝實現:
function getJSON(url) {
  // 建立一個 promise 物件
  let promise = new Promise(function(resolve, reject) {
    let xhr = new XMLHttpRequest();

    // 新建一個 http 請求
    xhr.open("GET", url, true);

    // 設定狀態的監聽函數
    xhr.onreadystatechange = function() {
      if (this.readyState !== 4) return;

      // 當請求成功或失敗時,改變 promise 的狀態
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };

    // 設定錯誤監聽函數
    xhr.onerror = function() {
      reject(new Error(this.statusText));
    };

    // 設定響應的資料型別
    xhr.responseType = "json";

    // 設定請求頭資訊
    xhr.setRequestHeader("Accept", "application/json");

    // 傳送 http 請求
    xhr.send(null);
  });
  return promise;
}

JQ Ajax、Axios、Fetch的核心區別

JQuery Ajax

Ajax前後端資料通訊「同源、跨域」

// 使用者登入 -> 登入成功 -> 獲取使用者資訊
/* 回撥地獄 */
$.ajax({
    url: 'http://127.0.0.1:8888/user/login',
    method: 'post',
    data: Qs.stringify({
        account: '18310612838',
        password: md5('1234567890')
    }),
    success(result) {
        if (result.code === 0) {
            // 登入成功
            $.ajax({
                url: 'http://127.0.0.1:8888/user/list',
                method: 'get',
                success(result) {
                    console.log(result);
                }
            });
        }
    }
});

優缺點:

  • 本身是針對MVC的程式設計,不符合現在前端MVVM的浪潮
  • 基於原生的XHR開發,XHR本身的架構不清晰,已經有了fetch的替代方案
  • JQuery整個專案太大,單純使用ajax卻要引入整個JQuery非常的不合理(採取個性化打包的方案又不能享受CDN服務)

Axios

Axios也是對ajax的封裝,基於Promise管理請求,解決回撥地獄問題

axios({
    method: 'post',
    url: '/user/login',
    data: {
        username: 'name',
        password: 'password'
    }
})
.then(function (response) {
    console.log(response);
})
.catch(function (error) {
    console.log(error);
});
// 或使用 async await
(async function () {
    let result1 = await axios.post('/user/login', {
        username: 'name',
        password: 'password'
    });
    let result2 = await axios.get('/user/list');
    console.log(result1, result2);
})(); 

優缺點:

  • 從瀏覽器中建立 XMLHttpRequest
  • 從 node.js 發出 http 請求
  • 支援 Promise API
  • 攔截請求和響應
  • 轉換請求和響應資料
  • 取消請求
  • 自動轉換JSON資料
  • 使用者端支援防止CSRF/XSRF

Fetch

Fetch是ES6新增的通訊方法,不是ajax,但是他本身實現資料通訊,就是基於promise管理的

try {
  let response = await fetch(url, options);
  let data = response.json();
  console.log(data);
} catch(e) {
  console.log("Oops, error", e);
}

範例:

(async function () {
    let result = await fetch('http://127.0.0.1:8888/user/login', {
        method: 'post',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        body: Qs.stringify({
            name: 'name',
            password: 'password'
        })
    })
    let data = result.json();
    console.log(data)
​
    let result2 = await fetch('http://127.0.0.1:8888/user/list').then(response => {
        return response.json();
    });
    console.log(result2);
})(); 

優缺點:

  • fetcht只對網路請求報錯,對400,500都當做成功的請求,需要封裝去處理
  • fetch預設不會帶cookie,需要新增設定項
  • fetch不支援abort,不支援超時控制,使用setTimeout及Promise.reject的實現的超時控制並不能阻止請求過程繼續在後臺執行,造成了量的浪費
  • fetch沒有辦法原生監測請求的進度,而XHR可以

補充:為什麼要用axios?

axios 是一個基於Promise 用於瀏覽器和 nodejs 的 HTTP 使用者端,它本身具有以下特徵:

  • 從瀏覽器中建立 XMLHttpRequest
  • 從 node.js 發出 http 請求
  • 支援 Promise API
  • 攔截請求和響應
  • 轉換請求和響應資料
  • 取消請求
  • 自動轉換JSON資料
  • 使用者端支援防止CSRF/XSRF
  • axios既提供了並行的封裝,也沒有fetch的各種問題,而且體積也較小,當之無愧現在最應該選用的請求的方式。

三選一絕必是axios了。其流程圖如下:

總結

到此這篇關於AJAX原理以及axios、fetch區別的文章就介紹到這了,更多相關AJAX原理 axios、fetch區別內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com