Ajax,jQuery ajax,axios和fetch介紹、區別以及優缺點

  • 2019 年 10 月 4 日
  • 筆記

中秋節快樂

三年前入職的時候還是一個只會使用Ajax和Jquery Ajax的菜鳥,由於早期Jquery不支援大文件請求的問題,要麼拆分文件,要麼用XHR~今天總結一篇數據請求的 進入今天的世界吧~~~

引言

前端的發展可以說是一個快速崛起的歷程了,不斷的進化,不斷的出現新的Api,新的功能,前端這個領域真的是一個發展飛快的領域,你前一天剛學會XXX的的運用,後一天某某某就革新了一項新的技術,你在感嘆學不動的同時,不得不繼續學習。扯遠了,回到我們今天的主題。。。

注意:以下篇幅較長,建議收藏了慢慢收看。在這裡學到的肯定會對你有所幫助。

這只是一個區別介紹

「Ajax」

全稱Asynchronous JavaScript and XML(非同步的 JavaScript 和 XML)最早出現的發送後端請求技術,隸屬於原始js中,核心使用XMLHttpRequest對象,多個請求之間如果有先後關係的話,就會出現回調地獄。

「Jquery Ajax」

是 jQuery 底層 AJAX 實現。簡單易用的高層實現見 $.get, $.post 等。$.ajax() 返回其創建的 XMLHttpRequest 對象。大多數情況下你無需直接操作該函數,除非你需要操作不常用的選項,以獲得更多的靈活性。jQuery ajax – ajax() 方法

「Axios」

axios不是原生JS的,需要進行安裝,它不但可以在客戶端使用,也可以在nodejs端使用。Axios也可以在請求和響應階段進行攔截。同樣也是基於[Promise]對象的。特性:從瀏覽器中創建 XMLHttpRequests、從 node.js 創建 http 請求、支援 Promise API、攔截請求和響應等。[Axios 中文文檔傳送門]

「Fetch」

Fetch 提供了對 Request 和 Response (以及其他與網路請求有關的)對象的通用定義。使之今後可以被使用到更多地應用場景中:無論是service workers、Cache API、又或者是其他處理請求和響應的方式,甚至是任何一種需要你自己在程式中生成響應的方式。`Fetch`號稱是AJAX的替代品,是在ES6出現的,使用了ES6中的[Promise]對象。Fetch是基於promise設計的。Fetch的程式碼結構比起ajax簡單多了,參數有點像jQuery ajax。注意,一定記住fetch不是ajax的進一步封裝,而是原生js。Fetch函數就是原生js。

進入細談環節

詳細的描述一下Ajax,jQuery ajax,axios和fetch區別,讓我們繼續往下研究。

01

Ajax = 非同步 JavaScript 和 XML

02

Ajax是一種用於創建快速動態網頁的技術

通過在後台與伺服器進行少量數據交換,AJAX 可以使網頁實現非同步更新。這意味著可以在不重新載入整個網頁的情況下,對網頁的某部分進行更新。

AJAX 工作原理

01

Ajax

[XMLHttpRequest]讓發送一個HTTP請求變得非常容易。你只需要簡單的創建一個請求對象實例,打開一個URL,然後發送這個請求。當傳輸完畢後,結果的[HTTP狀態]以及返回的響應內容也可以從請求對象中獲取。簡單的來敘述一下這個過程,往下看:

1-1

請求類型

通過XMLHttpRequest生成的請求可以有兩種方式來獲取數據,非同步模式同步模式。請求的類型是由這個XMLHttpRequest對象的open()方法的第三個參數async的值決定的。如果該參數的值為false,則該XMLHttpRequest請求以同步模式進行,否則該過程將以非同步模式完成。

注意:由於對用戶體驗的糟糕效果,從Gecko 30.0(Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27)版本開始,在主執行緒上的同步請求已經被棄用

1-2

處理響應

W3C規範定義了XMLHttpRequest對象的幾種類型的響應屬性。這些屬性告訴客戶端關於XMLHttpRequest返回狀態的重要資訊。一些處理非文本返回類型的用例可能包含一些下面章節描述的操作和分析。

分析並操作 responseXML屬性

如果你使用 XMLHttpRequest 來獲得一個遠程的 XML 文檔的內容,responseXML 屬性將會是一個由 XML 文檔解析而來的 DOM 對象,這很難被操作和分析。這裡有五種主要的分析 XML 文檔的方式

●1.使用XPath定位到文檔的指定部分。

●2.手工的解析和序列化XML 為字元串或對象。

●3.使用XMLSerializer把 DOM 樹序列化成字元串或文件。

●4.如果你預先知道 XML 文檔的內容,你可以使用 RegExp。如果你用 RegExp 掃描時受到換行符的影響,你也許想要刪除所有的換行符。然而,這種方法是"最後手段",因為如果 XML 程式碼發生輕微變化,該方法將可能失敗。

解析和操作包含 HTML 文檔的 responseText 屬性

如果使用 XMLHttpRequest 從遠端獲取一個 HTML 頁面,則所有 HTML 標記會以字元串的形式存放在responseText 屬性里,這樣就使得操作和解析這些標記變得困難。解析這些HTML標記主要有三種方式

XMLHttpRequestresponseXML 屬性。

●將內容通過fragment.body.innerHTML 注入到一個 文檔片段 中,並遍歷 DOM 中的片段。

●如果你預先知道 HTML 文檔的內容,你可以使用 RegExp。如果你用 RegExp 掃描時受到換行符的影響,你也許想要刪除所有的換行符。然而,這種方法是"最後手段",因為如果 HTML 程式碼發生輕微變化,該方法將可能失敗。

1-3

處理二進位數據

儘管 XMLHttpRequest 一般用來發送和接收文本數據,但其實也可以發送和接受二進位內容。有許多經過良好測試的方法來強制使用 XMLHttpRequest 發送二進位數據。利用 XMLHttpRequest.overrideMimeType() 方法是一個解決方案,雖然它並不是一個標準方法。

在 XMLHttpRequest Level 2 規範中新加入了 responseType 屬性 ,使得發送和接收二進位數據變得更加容易。

1-4

監測進度

XMLHttpRequest 提供了各種在請求被處理期間發生的事件以供監聽。這包括定期進度通知、 錯誤通知,等等。

支援 DOM 的 progress 事件監測之於 XMLHttpRequest 傳輸,遵循 Web API 進度事件規範 : 這些事件實現了 ProgressEvent 介面。

1-5

提交表單和上傳文件

XMLHttpRequest 的實例有兩種方式提交表單:

1

使用 Ajax

2

使用 FormData API

使用 FormData API 是最簡單最快捷的,但是缺點是被收集的數據無法使用JSON.stringify()轉換為一個 JSON字元串。第一種方式反而是最複雜的但也是最靈活和最強大。

請求方式這裡不做太多贅述,一個傳送門,有興趣的小夥伴可以自己去查閱一下。

02

Jquery Ajax

傳統 Ajax 指的是 XMLHttpRequest(XHR), 最早出現的發送後端請求技術,隸屬於原始js中,核心使用XMLHttpRequest對象,多個請求之間如果有先後關係的話,就會出現回調地獄。Jquery Ajax的出現是對原生XHR的封裝,除此以外還增添了對JSONP的支援,Jquery Ajax經過多年的更新維護,真的已經是非常的方便了,但是隨著react, vue, angular新一代框架的興起,以及ES規範的完善,更多API的更新,它逐漸暴露了自己的不足:

本身是針對MVC的編程,不符合現在前端MVVM的浪潮、配置和調用方式非常混亂,而且基於事件的非同步模型不友好

基於原生的XHR開發,XHR本身的架構不清晰,已經有了fetch的替代方案

JQuery整個項目太大,單純使用ajax卻要引入整個JQuery非常的不合理(採取個性化打包的方案又不能享受CDN服務)

不符合 關注點分離( Separation of Concerns )的原則

默認情況下,Ajax 請求使用 GET 方法。如果要使用 POST 方法,可以設定 type 參數值。這個選項也會影響 data 選項中的內容如何發送到伺服器。

data 選項既可以包含一個查詢字元串,比如 key1=value1&key2=value2 ,也可以是一個映射,比如 { key1: 'value1', key2: 'value2'} 。如果使用了後者的形式,則數據再發送器會被轉換成查詢字元串。這個處理過程也可以通過設置 processData 選項為 false 來迴避。如果我們希望發送一個 XML 對象給伺服器時,這種處理可能並不合適。並且在這種情況下,我們也應當改變 contentType 選項的值,用其他合適的 MIME 類型來取代默認的 application/x-www-form-urlencoded

下面的表格列出了 jQuery AJAX 方法:

執行非同步 AJAX 請求

對於Jquery Ajax來說我是特別的喜歡。

03

Axios

先來看看官網的案例:

執行 GET 請求

執行 POST 請求

執行多個並發請求

Vue2.0之後,尤雨溪推薦大家用axios替換JQuery ajax,未來App的趨勢是輕量化和細化,能解決問題的應用就是好應用,想必讓Axios進入了很多人的目光中。Axios本質上也是對原生XHR的封裝,只不過它是Promise的實現版本,可以用在瀏覽器和 node.js 中,符合最新的ES規範,從它的官網上可以看到它有以下幾條特性

從瀏覽器中創建 XMLHttpRequests。

從 node.js 創建 http 請求。

支援 Promise API。

攔截請求和響應

轉換請求數據和響應數據

取消請求

自動轉換 JSON 數據

客戶端支援防禦 XSRF

XSRF(Cross Site Request Forgery, 跨站域請求偽造)也稱 XSRF, 是一種網路的攻擊方式,它在 2007 年曾被列為互聯網 20 大安全隱患之一。其他安全隱患,比如 SQL 腳本注入,跨站域腳本攻擊等在近年來已經逐漸為眾人熟知,很多網站也都針對他們進行了防禦。然而,對於大多數人來說,CSRF 卻依然是一個陌生的概念。即便是大名鼎鼎的 Gmail, 在 2007 年底也存在著 CSRF 漏洞,從而被黑客攻擊而使 Gmail 的用戶造成巨大的損失。客戶端支援防禦 XSRF,是怎麼做到的呢,就是讓你的每個請求都帶一個從cookie中拿到的key, 根據瀏覽器同源策略,假冒的網站是拿不到你cookie中得key的,這樣,後台就可以輕鬆辨別出這個請求是否是用戶在假冒網站上的誤導輸入,從而採取正確的策略。

axios創建請求時可以用的配置選項。只有 url 是必需的。如果沒有指定 method,請求將默認使用 get 方法。請求配置傳送門(微信環境請點擊閱讀全文查看

Axios既提供了並發的封裝,體積也較小,也沒有下文會提到的fetch的各種問題,當之無愧是現在最應該選用的請求的方式。

04

Fetch

Fetch 提供了對 RequestResponse (以及其他與網路請求有關的)對象的通用定義。Fetch 是一個現代的概念, 等同於 XMLHttpRequest。它提供了許多與XMLHttpRequest相同的功能,但被設計成更具可擴展性和高效性。

Fetch API 提供了一個 JavaScript介面,用於訪問和操縱HTTP管道的部分,例如請求和響應。它還提供了一個全局 fetch()方法,該方法提供了一種簡單,合理的方式來跨網路非同步獲取資源。

請注意,fetch規範與jQuery.ajax()主要有兩種方式的不同,牢記:

當接收到一個代表錯誤的 HTTP 狀態碼時,從 fetch()返回的 Promise 不會被標記為 reject, 即使該 HTTP 響應的狀態碼是 404500。相反,它會將 Promise 狀態標記為 resolve但是會將 resolve 的返回值的 ok 屬性設置為 false ),僅當網路故障時或請求被阻止時,才會標記為 reject

默認情況下,fetch 不會從服務端發送或接收任何 cookies, 如果站點依賴於用戶 session,則會導致未經認證的請求(要發送 cookies,必須設置 credentials 選項)。自從2017年8月25日後,默認的credentials政策變更為same-originFirefox也在61.0b13中改變默認值

一個基本的 fetch請求設置起來很簡單。看看下面的程式碼:

這裡我們通過網路獲取一個JSON文件並將其列印到控制台。最簡單的用法是只提供一個參數用來指明想fetch()到的資源路徑,然後返回一個包含響應結果的promise(一個 Response 對象)

當然它只是一個 HTTP 響應,而不是真的JSON。為了獲取JSON的內容,我們需要使用 json()方法(在Bodymixin 中定義,被 Request 和 Response 對象實現)。

fetch() 接受第二個可選參數,一個可以控制不同配置的 init 對象:

fetch的優點

1

語法簡潔,更加語義化

2

基於標準Promise實現,支援async/await。

3

同構方便,使用isomorphic-fetch

4

更加底層,提供的API豐富(request, response)

5

脫離了XHR,是ES規範里新的實現方式

fetch在前端的應用上有一項xhr怎麼也比不上的能力:跨域的處理

我們都知道因為同源策略的問題,瀏覽器的請求是可能隨便跨域的——一定要有跨域頭或者藉助JSONP,但是,fetch中可以設置mode為"no-cors"(不跨域),如下所示:

這樣之後我們會得到一個type為「opaque」的返回。需要指出的是,這個請求是真正抵達過後台的,所以我們可以使用這種方法來進行資訊上報,在我們之前的image.src方法中多出了一種選擇,另外,我們在network中可以看到這個請求後台設置跨域頭之後的實際返回,有助於我們提前調試介面(當然,通過chrome插件我們也可以做的到)。

總結如有不當,如有錯誤,還望不吝賜教。