Ajax、fetch、axios的區別與優缺點

Lan.ZerGan發表於2018-11-30

背景

前端的技術發展速度非常的快,非同步請求也是其重要的體現之一,從最早的原生XHR,再到JqueryAjax的統治時代,再到近來,fetch、axios等技術也開始出現並大量投入使用。

原生Ajax

Ajax是指一種建立互動式網頁應用的網頁開發技術,並且可以做到無需重新載入整個網頁的情況下,能夠更新部分網頁,也叫作區域性更新。

XMLHttpRequest 物件

使用ajax傳送請求是依靠於一個物件,叫XmlHttpRequest物件,通過這個物件我們可以從伺服器獲取到資料,然後再渲染到我們的頁面上。現在幾乎所有的瀏覽器都有這個物件,只有IE7以下的沒有,而是通過ActiveXObject這個物件來建立的。XmlHttpRequest物件有一些常見的方法:

方法描述
abort()停止當前請求
getAllResponseHeaders()把HTTP請求的所有響應首部作為鍵/值對返回
getResponseHeader(“header”)返回指定首部的串值
open(method,url)建立對伺服器的呼叫,還有3個可選引數,是否非同步、使用者名稱、密碼
send(content)向伺服器傳送請求
abort()停止當前請求
setRequestHeader(header, value)把指定首部設定為所提供的值。

ajax使用步驟

1.建立XmlHttpRequest物件
2.呼叫open方法設定基本請求資訊
3.設定傳送的資料,傳送請求
4.註冊監聽的回撥函式
5.拿到返回值,對頁面進行更新

ajax的get/post請求

其實get和post的請求方式大致是相同的,下面分別是get和post的示例程式碼:
get

    <script>
       //步驟一:建立非同步物件
       var xhr = new XMLHttpRequest();
       //步驟二:設定請求的基本引數
       xhr.open('get','test.php');
       //步驟三:傳送請求
       xhr.send();
       //步驟四:註冊onreadystatechange監聽事件,只要狀態改變就會呼叫
       xhr.onreadystatechange = function () {
          if (ajax.readyState == 4 && ajax.status == 200) {
           //步驟五 如果能夠進到這個判斷 說明資料完美到手
           console.log(ajax.responseText);//操作返回內容
           }
       }
    </script>

post

    <script>
        //建立非同步物件  
        var xhr = new XMLHttpRequest();
        //設定請求基本資訊,並加上請求頭
        xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
        xhr.open('post', 'test.php' );
        //傳送請求
        xhr.send('name=Lan&age=18');
        xhr.onreadystatechange = function () {
            // 這步為判斷伺服器是否正確響應
          if (xhr.readyState == 4 && xhr.status == 200) {
            console.log(xhr.responseText);
          } 
        };
    </script>

onreadystatechange
這個監聽函式是來監聽readyState這個狀態值得:

狀態值描述
0請求還未初始化,還未呼叫open( )
1請求已建立但未傳送,還未呼叫send( )
2接受原始響應資料,為解析做準備
3正在解析資料,根據響應頭部返回的MIME型別把資料轉換成能通過responseText等形式存取的格式
4響應完成,資料解析完成

ajax優缺點

優缺點描述
優點區域性更新
優點原生支援,不需要任何外掛
優點原生支援,不需要任何外掛
缺點可能破壞瀏覽器後退功能
缺點巢狀回撥,難以處理

JqueryAjax

其實Jquery的ajax就是在原生的ajax的基礎上進行了封裝,其實沒有太多好說的東西,不過加上了對JSONP的支援,附上例子:

    <script>
        var loginBtn =  document.getElementsByTagName("button")[0];
        loginBtn.onclick = function(){
        
            ajax({
                type:"post",
                url:"test.php",
                data:"name=lan&pwd=123456",
                success:function(data){
                   console.log(data);
                }
            });
        }
    </script>

ajax方法裡面需要傳入一個物件引數,裡面包括了一些常見的引數,其實jquery維護了這麼多年了,ajax請求其實已經很方便了,如果非要說有什麼缺點的話,就是依然對回撥巢狀不方便,然後就是如果為了一個JqueryAjax就引入整個jquery,檔案比較大,成本過高。

Fetch

Fetch是ajax非常好的一個替代品,很有可能將來會完全代替ajax的地位。我們先來看下瀏覽器的支援情況:
Fetch瀏覽器支援情況
我們可以看到IE瀏覽器完全不支援Fetch,並且移動端的很多瀏覽器也不支援Fetch,不過可以使用第三方的ployfill來獲得支援。Github.fetch

Fetch寫法

不管是原生的Ajax還是Jquery封裝的Ajax都有一個問題就在於回撥地獄,fetch很友好的解決了這個問題,fetch大概長這個樣子:

fetch(...).then(fun2)
          .then(fun3)
          .....
          .catch(fun)

它給人一種同步的流程來書寫非同步的操作,成功的解決了回撥地獄的問題。Fetch能做到這一點,是因為Fetch API是基於Promise設計的。並且fetch呼叫非常簡單,因為它是掛在BOM上的,屬於全域性的方法。

Fetch獲取資料

我們使用Fetch來獲取資料時,會返回給我們一個Pormise物件,我們簡單看一下:

    <script>
        fetch("http://www.abc.cn/test")
            .then(Response => {
                console.log(Response);
            })
    </script>

輸出如下:
輸出
OK就是true,status是200,我們可以看到這裡面並沒有我們想要的資料,其實資料都在body屬性裡面,是一種資料流的形式,一般伺服器會給我們返回JSON資料的格式,我們可以呼叫response.json來轉化下資料:

    <script>
        fetch("http://www.abc.cn/test")
            .then(Response => Response.json())
            .then(data => {
                console.log(data);
            })
    </script>

處理之後,我們繼續.then就可以拿到處理之後的資料了。所以這麼來看的話通過Fetch來獲取資料是非常簡潔簡單的。

Fetch傳送資料

Fetch傳送資料也非常的簡單,API長這樣:

	fetch(url,options)

第二個引數會傳入一個物件來配置請求的資訊。下面先看一個例子:

    <script>
        fetch('http://www.mozotech.cn/bangbang/index/user/login', {
          method: 'post',
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
          },
          body: new URLSearchParams([["username", "Lan"],["password", "123456"]]).toString()
        })
        .then(res => {
            console.log(res);
            return res.text();
        })
        .then(data => {
            console.log(data);
        })
    </script>

對傳入的引數做個說明:

引數名描述
method請求的方法,預設GET
headers請求的頭資訊
body請求的內容主體

值得一提的是,fetch預設的post的header是Content-Type:text/plain;charset=UTF-8,不過通常我們的post請求是通過表單的形式提交的。所以我們需要把header修改為:Content-Type:application/x-www-form-urlencoded

Cookie傳遞

fetch傳送請求時,不像XHR,因為它預設是不帶上Cookie的,如果站點依賴於維護一個使用者會話,可能導致未經認證的請求,所以我們需要手動的把Cookie帶上,只需加上 credentials: 'include'即可:

    <script>
        fetch('https://www.abc.com/search', {
            method: 'GET',
            credentials: 'include' // 強制加入Cookie
          })
          .then((res)=>{
            return res.text()
          })
          .then((res)=>{
            console.log(res)
          })
    </script>

Fetch優缺點

優缺點描述
優點解決回撥地獄
優點使用起來更加簡潔
缺點API 偏底層,需要封裝
缺點預設不帶Cookie,需要手動新增
缺點瀏覽器支援情況不是很友好,需要第三方的ployfill

Axios

Vue2.0之後,axios開始受到更多的歡迎了。其實axios也是對原生XHR的一種封裝,不過是Promise實現版本。
它是一個用於瀏覽器和 nodejs 的 HTTP 客戶端,符合最新的ES規範。簡單看下如何使用即可

    <script>
        axios({
            method: 'post',
            url: '/abc/login',
            data: {
                userName: 'Lan',
                password: '123'
            }
        })
        .then(function (response) {
            console.log(response);
        })
        .catch(function (error) {
            console.log(error);
        });
    </script>

感覺axios算是比較完美的一種方案了,幾乎沒有什麼大的缺點。

總結

其實有這麼多種的請求方法和解決方案,總結一下:原生XHR幾乎很少開發會用,JqueryAjax屬於老當益壯的那種,雖然很老,但是很好用,Fetch是屬於初生牛犢,還需要慢慢成長,axios就目前來說,算是非常好的了,無腦使用即可。

相關文章