ajax到fetch和axios

1- AJAX異步原理與實現

Ajax的工做原理至關於在用戶和服務器之間加了一箇中間層(ajax引擎),使用戶操做與服務器響應異步化。並非全部的用戶請求都提交給服務器,像—些數據驗證(好比判斷用戶是否輸入了數據)和數據處理(好比判斷用戶輸入數據是不是數字)等都交給Ajax引擎本身來作, 只有肯定須要從服務器讀取新數據時再由Ajax引擎代爲向服務器提交請求。把這些交給了Ajax引擎,用戶操做起來也就感受更加流暢了。前端

看了網上前輩們寫的資料,我本身總結概括ajax的原理和流程以下:node

一、AJAX建立異步對象XMLHttpRequest

這個是ajax核心的對象, 如下代碼是chrome瀏覽器和兼容IE瀏覽器的版本jquery

var ajax = {};
ajax.httpRequest = function () {
    //判斷是否支持XMLHttpRequest對象
    if (window.XMLHttpRequest) {
        return new XMLHttpRequest();
    }
    //兼容IE瀏覽器
    var versions = [
        "MSXML2.XmlHttp.6.0",
        "MSXML2.XmlHttp.5.0",
        "MSXML2.XmlHttp.4.0",
        "MSXML2.XmlHttp.3.0",
        "MSXML2.XmlHttp.2.0",
        "Microsoft.XmlHttp"
    ];
    //定義局部變量xhr,儲存IE瀏覽器的ActiveXObject對象
    var xhr;
    for (var i = 0; i < versions.length; i++) {
        try {
            xhr = new ActiveXObject(versions[i]);
            break;
        } catch (e) {
        }
    }
    return xhr;
};

複製代碼

二、Ajax優缺點

Ajax的優勢

1.無刷新更新數據。
2.異步與服務器通訊。
3.前端和後端負載平衡。
4.基於標準被普遍支持。
5.界面與應用分離。
複製代碼

Ajax缺點

1.AjAX幹掉了Back和加入收藏書籤功能,即對瀏覽器機制的破壞。
2.AJAX的安全問題。
3.由於網絡延遲須要給用戶提供必要提示
複製代碼

2- 操做XMLHttpRequest 對象

Ajax(Asynchronous JavaScript and XML)不是指一種單一的技術,而是有機地利用了一系列相關的技術。雖然其名稱包含XML,但實際上數據格式能夠由JSON代替,進一步減小數據量,造成所謂的AJAJ。爲了使用JavaScript向服務器發出 HTTP 請求,須要一個提供此功能的類的實例。這就是XMLHttpRequest的由來。這樣的類最初是在Internet Explorer中做爲一個名爲XMLHTTP的ActiveX對象引入的。而後,Mozilla,Safari和其餘瀏覽器,實現一個XMLHttpRequest類,支持Microsoft的原始ActiveX對象的方法和屬性。同時微軟也實現了XMLHttpRequest。ios

一、使用xhr對象。

(1)設置請求參數(請求方式,請求頁面的相對路徑,是否異步)
(2)設置回調函數,一個處理服務器響應的函數,使用 onreadystatechange ,相似函數指針
(3)獲取異步對象的readyState 屬性:該屬性存有服務器響應的狀態信息。每當 readyState 改變時,onreadystatechange 函數就會被執行。
(4)判斷響應報文的狀態,若爲200說明服務器正常運行並返回響應數據,
(5)讀取響應數據,能夠經過 responseText 屬性來取回由服務器返回的數據。
複製代碼

二、XMLhttpRequest屬性

onreadystatechangees6

一個JavaScript函數對象,當readyState屬性改變時會調用它。回調函數會在user interface線程中調用。ajax

readyStatechrome

HTTP 請求的狀態.當一個 XMLHttpRequest 初次建立時,這個屬性的值從 0 開始,直到接收到完整的 HTTP 響應,這個值增長到 4。json

5個狀態中每個都有一個相關聯的非正式的名稱,下表列出了狀態、名稱和含義:axios

狀態 名稱 描述
0 Uninitialized 初始化狀態。XMLHttpRequest 對象已建立或已被 abort() 方法重置。
1 Open open() 方法已調用,可是 send() 方法未調用。請求尚未被髮送。
2 Sent Send() 方法已調用,HTTP 請求已發送到 Web 服務器。未接收到響應。
3 Receiving 全部響應頭部都已經接收到。響應體開始接收但未完成。
4 Loaded HTTP 響應已經徹底接收。

readyState 的值不會遞減,除非當一個請求在處理過程當中的時候調用了 abort() 或 open() 方法。每次這個屬性的值增長的時候,都會觸發 onreadystatechange 事件句柄。後端

responseText

目前爲止爲服務器接收到的響應體(不包括頭部),或者若是尚未接收到數據的話,就是空字符串。

若是 readyState 小於 3,這個屬性就是一個空字符串。當 readyState 爲 3,這個屬性返回目前已經接收的響應部分。若是 readyState 爲 4,這個屬性保存了完整的響應體。

若是響應包含了爲響應體指定字符編碼的頭部,就使用該編碼。不然,假定使用 Unicode UTF-8。

responseXML

對請求的響應,解析爲 XML 並做爲 Document 對象返回。

status

由服務器返回的 HTTP 狀態代碼,如 200 表示成功,而 404 表示 "Not Found" 錯誤。當 readyState 小於 3 的時候讀取這一屬性會致使一個異常。

statusText

這個屬性用名稱而不是數字指定了請求的 HTTP 的狀態代碼。也就是說,當狀態爲 200 的時候它是 "OK",當狀態爲 404 的時候它是 "Not Found"。和 status 屬性同樣,當 readyState 小於 3 的時候讀取這一屬性會致使一個異常。

三、XMLHttpRequest方法

abort()

取消當前響應,關閉鏈接而且結束任何未決的網絡活動。

這個方法把 XMLHttpRequest 對象重置爲 readyState 爲 0 的狀態,而且取消全部未決的網絡活動。例如,若是請求用了太長時間,並且響應再也不必要的時候,能夠調用這個方法。

getAllResponseHeaders()

把 HTTP 響應頭部做爲未解析的字符串返回。

若是 readyState 小於 3,這個方法返回 null。不然,它返回服務器發送的全部 HTTP 響應的頭部。頭部做爲單個的字符串返回,一行一個頭部。每行用換行符 "\r\n" 隔開。

getResponseHeader()

返回指定的 HTTP 響應頭部的值。其參數是要返回的 HTTP 響應頭部的名稱。可使用任何大小寫來制定這個頭部名字,和響應頭部的比較是不區分大小寫的。

該方法的返回值是指定的 HTTP 響應頭部的值,若是沒有接收到這個頭部或者 readyState 小於 3 則爲空字符串。若是接收到多個有指定名稱的頭部,這個頭部的值被鏈接起來並返回,使用逗號和空格分隔開各個頭部的值。

open()

初始化一個請求. 該方法用於JavaScript代碼中;若是是本地代碼, 使用 openRequest())方法代替.

注意: 在一個已經激活的request下(已經調用open()或者openRequest()方法的request)再次調用這個方法至關於調用了abort()方法。

參數

  • method

請求所使用的HTTP方法; 例如 "GET", "POST", "PUT", "DELETE"等. 若是下個參數是非HTTP(S)的URL,則忽略該參數.

  • url

該請求所要訪問的URL

  • async

一個可選的布爾值參數,默認爲true,意味着是否執行異步操做,若是值爲false,則send()方法不會返回任何東西,直到接受到了服務器的返回數據。若是爲值爲true,一個對開發者透明的通知會發送到相關的事件監聽者。這個值必須是true,若是multipart 屬性是true,不然將會出現一個意外。

  • user

用戶名,可選參數,爲受權使用;默認參數爲空string.

  • password

密碼,可選參數,爲受權使用;默認參數爲空string.

send()

發送 HTTP 請求,使用傳遞給 open() 方法的參數,以及傳遞給該方法的可選請求體。

setRequestHeader()

向一個打開但未發送的請求設置或添加一個 HTTP 請求(設置請求頭)。 參數

  • header

將要被賦值的請求頭名稱

  • value

給指定的請求頭賦的值

四、原生Js的ajax

ajax.send = function (url, callback, method, data, async) {
    //默認異步
    if (async === undefined) {
        async = true;
    }
    var httpRequest = ajax.httpRequest();
    //初始化HTTP請求
    httpRequest.open(method, url, async);
    //onreadystatechange函數對象
    httpRequest.onreadystatechange = function () {
        //readyState 的值等於4,從服務器拿到了數據
        if (httpRequest.readyState == 4) {
            //回調服務器響應數據
            callback(httpRequest.responseText)
        }
    };
    if (method == 'POST') {
          //給指定的HTTP請求頭賦值
        httpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    }
      //發送HTTP請求
    httpRequest.send(data);
};
//實現GET請求
ajax.get = function (url, data, callback, async) {
    var query = [];
    for (var key in data) {
        query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
    }
    ajax.send(url + (query.length ? '?' + query.join('&') : ''), callback, 'GET', null, async)
};
//實現POST請求
ajax.post = function (url, data, callback, async) {
    var query = [];
    for (var key in data) {
        query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
    }
    ajax.send(url, callback, 'POST', query.join('&'), async)
};

複製代碼

五、jQuery的ajax

$.ajax({
        type: "", 請求方式
        url: "", // 請求路徑
        async: true, // 默認是異步
        data: JSON.stringify({ obj }),
        contentType: 'application/json;charset=utf-8', // 設置contentType
        success: function(res) { 
            console.log(res)
        },
        error: function(err) {
            console.log(err)
        }
        
    )
複製代碼

六、JSON格式

在線JSON校驗格式化工具

一、key添加雙引號
二、末尾沒有分號
三、同一個對象不容許有兩個同名屬性
複製代碼

序列化

JSON.stringify() // JSON對象轉換成JSON字符串
JSON.parse()     // JSON對象轉換成JSON字符串
複製代碼

3- fetch

fetch號稱是ajax的替代品,它的API是基於Promise設計的,舊版本的瀏覽器不支持Promise,須要使用polyfill es6-promise

// 原生XHR
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText)   // 從服務器獲取數據
    }
}
xhr.send()
// fetch
fetch(url)
    .then(response => {
        if (response.ok) {
            response.json()
        }
    })
    .then(data => console.log(data))
    .catch(err => console.log(err))

複製代碼

在MDN上,講到它跟jquery ajax的區別,這也是fetch很奇怪的地方:

當接收到一個表明錯誤的 HTTP 狀態碼時,從 fetch()返回的 Promise 不會被標記爲 reject, 即便該 HTTP 響應的狀態碼是 404 或 500。相反,它會將 Promise 狀態標記爲 resolve (可是會將 resolve 的返回值的 ok 屬性設置爲 false ), 僅當網絡故障時或請求被阻止時,纔會標記爲 reject。 默認狀況下, fetch 不會從服務端發送或接收任何 cookies, 若是站點依賴於用戶 session,則會致使未經認證的請求(要發送 cookies,必須設置 credentials 選項).

忽然感受這還不如jquery ajax好用呢?別急,再搭配上async/await將會讓咱們的異步代碼更加優雅:

async function test() {
    let response = await fetch(url);
    let data = await response.json();
    console.log(data)
}

複製代碼

看起來是否是像同步代碼同樣?簡直完美!好吧,其實並不完美,async/await是ES7的API,目前還在試驗階段,還須要咱們使用babel進行轉譯成ES5代碼。

還要提一下的是,fetch是比較底層的API,不少狀況下都須要咱們再次封裝。 好比:

// jquery ajax
$.post(url, {name: 'test'})
// fetch
fetch(url, {
    method: 'POST',
    body: Object.keys({name: 'test'}).map((key) => {
        return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
    }).join('&')
})

複製代碼

因爲fetch是比較底層的API,因此須要咱們手動將參數拼接成'name=test'的格式,而jquery ajax已經封裝好了。因此fetch並非開箱即用的。

另外,fetch還不支持超時控制。

哎呀,感受fetch好垃圾啊,,還須要繼續成長。。

4- axios

axios是尤雨溪大神推薦使用的,它也是對原生XHR的封裝。它有如下幾大特性:

  • 能夠在node.js中使用
  • 提供了併發請求的接口
  • 支持Promise API

簡單使用

axios({
    method: 'GET',
    url: url,
})
.then(res => {console.log(res)})
.catch(err => {console.log(err)})
複製代碼

並行開發

function getUserAccount() {
  return axios.get('/user/12345');
}

function getUserPermissions() {
  return axios.get('/user/12345/permissions');
}

axios.all([getUserAccount(), getUserPermissions()])
  .then(axios.spread(function (acct, perms) {
    // Both requests are now complete
  }));
複製代碼
相關文章
相關標籤/搜索