
作者 | Harsh Patel
前端開發最重要的部分之一是通過發出HTTP請求與後端進行通信,我們有幾種方法可以異步地在JavaScript中進行API調用。
幾年前,大多數應用程式都使用Ajax發送HTTP請求,Ajax代表異步JavaScript和XML。但是現在,開發人員通常會決定在 .fetch() API和Axios之間進行選擇。
在本文中,我想比較這兩種方法,并簡要介紹一下基本知識和文法。除此之外,我還将比較在兩種情況下以及在錯誤進行中将資料轉換為jsON格式的過程。我還将讨論HTTP攔截和下載下傳進度。
開始吧!
Fetch概述和文法
在建構Javascript項目時,我們可以使用window對象,并且它帶有許多可以在項目中使用的出色方法。這些功能之一是Fetch API,它提供了一種簡單的全局 .fetch() 方法,這是一種從API異步擷取資料的邏輯解決方案。
讓我們看一下 .fetch() 方法的文法。
fetch(url)
.then((res) =>
// handle response
)
.catch((error) => {
// handle error
})
在上面的示例中,您可以看到簡單的擷取GET請求的文法。在 .fetch() 方法中,我們有一個強制性參數url,它傳回一個Promise,可以使用Response對象來解決。
.fetch() 方法的第二個參數是選項,它是可選的。如果我們不傳遞 options,請求總是GET,它從給定的URL下載下傳内容。
在選項參數裡面,我們可以傳遞方法或頭資訊,是以如果我們想使用POST方法或其他方法,我們必須使用這個可選的數組。
正如我之前提到的,Promise會傳回Response對象,正因為如此,我們需要使用另一個方法來擷取響應的主體。有幾種不同的方法可以使用,取決于我們需要的格式:
response.json()
response.text()
response.formData()
response.blob()
response.arrayBuffer()
讓我們看一下帶有可選參數的代碼示例。
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
.then((response) => response.json())
.catch((error) => console.log(error))
在上面的代碼示例中,你可以看到簡單的POST請求,包括 method、header 和 body params。然後我使用 json() 方法将響應轉換為JSON格式。
現在,讓我們仔細看看axios。
Axios概述和文法
Axios是一個Javascript庫,用于從Node.js或XMLHttpRequests或浏覽器發出HTTP請求。作為一個現代的庫,它是基于Promise API的。
axios 有一些優勢,比如對XSRF的保護或取消請求。
為了能夠使用 axios 庫,我們必須将其安裝并導入到我們的項目中。可以使用CDN,npm或bower安裝 axios。現在,讓我們來看一個簡單的GET方法的文法。
axios.get(url)
.then(response => console.log(response));
.catch((error) => console.log(error));
在上面的代碼中,你可以看到我使用 .get() 方法建立一個簡單的GET請求。如果你想在函數中使用POST方法,那麼隻需使用 .post() 方法代替,并将請求資料作為參數傳遞即可。
當我們建立配置對象時,我們可以定義一堆屬性,最常見的是:
baseUrl
params
headers
auth
responseType
作為響應,axios 傳回一個promise,該promise将與響應對象或錯誤對象一起解析。在響應對象中,具有以下值:
data,這是實際的響應主體
status,調用的HTTP狀态,例如200或404
statusText,以文本消息形式傳回的HTTP狀态,例如 ok
headers,伺服器發回标頭
config,請求配置
request,XMLHttpRequest對象
現在,讓我們看一下帶有資料的POST方法的代碼示例。
axios.post({
'/url',
{ name: 'John', age: 22},
{ options }
})
在上面的代碼中,你可以看到 post 方法,我們把config對象作為param,其中有URL、資料和附加選項。
我們還可以将config對象定義為變量,然後像下面的示例一樣将其傳遞給 axios。
const config = {
url: 'http://api.com',
method: 'POST',
header: {
'Content-Type': 'application/json'
},
data: {
name: 'John',
age: 22
}
}
axios(config);
在這裡,你可以看到所有的參數,包括URL、資料或方法,都在config對象中,是以在一個地方定義所有的東西可能更容易。
JSON
如前所述,當我們在使用 .fetch() 方法的時候,需要對響應資料使用某種方法,當我們在發送帶有請求的body時,需要對資料進行字元串化。
在 axios 中,它是自動完成的,是以我們隻需在請求中傳遞資料或從響應中擷取資料。它是自動字元串化的,是以不需要其他操作。
讓我們看看如何從 fetch() 和 axios 擷取資料。
// fetch
fetch('url')
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.log(error))
// axios
axios.get('url')
.then((response) => console.log(response))
.catch((error) => console.log(error))
在上面的例子中,你可以看到,使用 axios 我們沒有額外的一行代碼,在 .fetch()的例子中,我們必須将資料轉換為JSON格式。在一個較大的項目中,如果你建立了大量的調用,那麼使用 axios 來避免重複代碼會更舒服。
錯誤處理
在這一點上,我們還需要給 axios 點贊,因為處理錯誤是非常容易的。
如果出現像404這樣的錯誤響應,promise就會被拒絕并傳回一個錯誤,是以我們需要捕獲一個錯誤,我們可以檢查它是什麼類型的錯誤,就是這樣。
讓我們看看代碼示例。
axios.get('url')
.then((response) => console.log(response))
.catch((error) => {
if (error.response) {
// When response status code is out of 2xx range
console.log(error.response.data)
console.log(error.response.status)
console.log(error.response.headers)
} else if (error.request) {
// When no response was recieved after request was made
console.log(error.request)
} else {
// Error
console.log(error.message)
}
})
在上面的代碼中,當響應良好時,我傳回了資料,但是如果請求以任何方式失敗,我就能夠檢查 .catch() 部分中的錯誤類型并傳回正确的消息。
對于 .fetch() 方法,就比較複雜了。每次我們從 .fetch() 方法中得到響應時,我們需要檢查狀态是否成功,因為即使不是,我們也會得到響應。
在 .fetch() 的情況下,隻有當請求沒有完成時,promise才會被解決。讓我們看一下代碼示例。
fetch('url')
.then((response) => {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json()
})
.then((data) => console.log(data))
.catch((error) => console.log(error))
在這段代碼中,我已經在承諾對象中檢查了代碼的狀态,如果響應有狀态 ok,那麼我就可以處理并使用 .json() 方法,但如果沒有,我必須在 .then() 裡面傳回錯誤。
為了友善和正确的錯誤處理,對于你的項目來說,axios 絕對會是一個更好的解決方案,但如果你正在建構一個隻有一兩個請求的小項目,使用 .fetch() 是可以的,但你需要記住正确處理錯誤。
下載下傳進度
當我們需要下載下傳大量的資料時,一種跟蹤進度的方法會很有用,特别是當使用者的網絡速度很慢時。早期,為了實作進度名額,開發者使用了 XMLHttpRequest.onprogress 回調。在 .fetch() 和 axios 中,有不同的方法來實作。
為了在 .fetch() 中跟蹤下載下傳進度,我們可以使用其中一個 response.body 屬性,一個 ReadableStream 對象。它逐塊提供主體資料,并允許我們計算時間消耗了多少資料。
在axios中,實作一個進度訓示器也是可能的,而且更容易,因為存在一個現成的子產品,可以安裝和實作,它叫做Axios Progress Bar。
如果你有大量的大資料要下載下傳,你想跟蹤進度名額的進度,你可以用 axios 來管理,更容易更快,但 .fetch() 也提供了這種可能性,隻是它需要更多的代碼來開發同樣的結果。
HTTP攔截
當我們需要檢查或改變我們從應用程式到伺服器的HTTP請求時,或者以其他方式,例如,為了驗證,HTTP攔截可能是重要的。
在 axios 的情況下,HTTP攔截是這個庫的關鍵功能之一,這就是為什麼我們不需要建立額外的代碼來使用它。讓我們看一下代碼示例,看看我們能做到多麼容易。
// 請求攔截
axios.interceptors.request.use((config) => {
console.log('Request sent');
})
// 響應攔截
axios.interceptors.response.use((response) => {
// do an operation on response
return response
})
axios.get('url')
.then((response) => console.log(response))
.catch((error) => console.log(error))
在代碼中,您可以看到請求攔截和響應攔截。在第一種情況下,我建立了一個 console.log,告知發送請求的情況,在響應攔截中,我們可以對響應做任何操作,然後傳回。
.fetch() 預設不提供HTTP攔截功能,我們可以覆寫 .fetch() 方法,定義發送請求過程中需要發生的事情,當然,這需要更多的代碼,可能比使用 axios 功能更複雜。
總結
在這篇文章中,我比較了用于建立HTTP請求的兩種方法,從簡單的概述開始,通過文法和一些重要的功能,如下載下傳進度或錯誤處理。
通過比較可以看出,對于有大量HTTP請求,需要良好的錯誤處理或HTTP攔截的應用,Axios是一個更好的解決方案。在小型項目的情況下,隻需要幾個簡單的API調用,Fetch也是一個不錯的解決方案。
在選擇項目的最佳解決方案時,還要注意一個因素,這是非常重要的。大多數浏覽器和Node.js環境都支援Axios,而現代浏覽器僅支援Fetch,并且某些版本可能會與舊版本一起釋出。
通過這些知識的了解,希望大家能夠選擇出最适合自己的方案,也希望大家覺得這個比較有幫助。
本文完~