譯者 | 陳豪
審校 | 梁策 孫淑娟
如果我們想從 API中獲取數(shù)據(jù)或?qū)?shù)據(jù)發(fā)布到服務(wù)器,必須要用到Fetch API。fetch()為我們提供了一種通過請(qǐng)求和響應(yīng)發(fā)送和接收 HTTP 請(qǐng)求的方法,fetch() 函數(shù)是一個(gè)全局函數(shù),最常用于與 API 交互。
如何在 JavaScript 中使用 Fetch
我們?cè)谑褂肍etch API獲取 URL的數(shù)據(jù)時(shí),最基本的用法只需要一個(gè)參數(shù)。當(dāng)我們運(yùn)行 Fetch 時(shí),它會(huì)有一個(gè)返回值:
let fetchExample = fetch("https://fjolt.com").then((res) => {
// Do something with res
});
Res包含一些很有意思的內(nèi)置函數(shù),如下:
- res.text() :返回 URL 的文本內(nèi)容。如果是網(wǎng)站,則返回 HTML。
- res.json() :返回格式化的 JSON 數(shù)據(jù)。
- res.blob() : 返回 blob 數(shù)據(jù)。
- res.arrayBuffer():返回?cái)?shù)組緩沖區(qū)數(shù)據(jù)
- res.formData() :返回 formData 數(shù)據(jù)。
下面是兩個(gè)例子:
使用 JavaScript Fetch 獲取網(wǎng)站的 HTML 內(nèi)容
由于res.text()具有可以獲取URL 的文本內(nèi)容的功能,所以可以使用它來獲取網(wǎng)站的整個(gè) HTML 。一旦運(yùn)行 res.text(),我們可以用另一個(gè) then 捕獲響應(yīng)并在控制臺(tái)記錄它:
let websiteData = fetch("https://fjolt.com").then(res => res.text()).then((data) => {
return data;
});
// Now contains our website's HTML.
如果鏈接不存在或發(fā)生錯(cuò)誤,響應(yīng)對(duì)象將返回錯(cuò)誤。例如,找不到頁面將返回 404,或者網(wǎng)關(guān)錯(cuò)誤將返回 502。
使用 JavaScript Fetch 從鏈接中獲取 JSON 內(nèi)容
Fetch 的另一個(gè)常見用途是獲取數(shù)組的響應(yīng)。如果想從 JSON 格式的 API 中獲取響應(yīng),我們可以使用 res.json()。例如,以下代碼將從 URL 返回一個(gè) JSON 對(duì)象,假設(shè) URL 正在發(fā)送有效的 JSON:
let apiResponse = fetch("https://fjolt.com/api").then(res => res.json()).then((data) => {
return data;
});
// Now contains a JSON object - assuming one exists
JavaScript Fetch 的選項(xiàng)
由于 Fetch 可以發(fā)送和接收 HTTP 請(qǐng)求,當(dāng)我們想要使用它獲取 URL數(shù)據(jù)的時(shí)候,還可以帶一些選項(xiàng),即 fetch(URL, { options })。如果你以前使用過 HTTP 請(qǐng)求就會(huì)對(duì)這很熟悉了。所有可用選項(xiàng)的示例,如下所示:
fetch("https://fjolt.com/", {
body: JSON.stringify({ someData: "value" })
method: 'POST'
mode: 'cors'
cache: 'no-cache'
credentials: 'same-origin'
headers: {
'Content-Type': 'application/json'
},
redirect: 'follow'
referrerPolicy: 'no-referrer'
});
以下是這些選項(xiàng)的具體含義:
- body:包含文本的主體。 在這個(gè)例子中,我們發(fā)送一些 JSON,它必須被字符串化。
- method:標(biāo)準(zhǔn)的 HTTP 方法。它可以是 POST/GET/DELETE/PUT/CONNECT/PATCH/TRACE/OPTIONS。
- mode:指是否接受跨域請(qǐng)求,它可以是cors/no-cors/same-origin。
- cache:指瀏覽器如何與Cache交互。 它可以是 default/no-cache/reload/force-cache/only-if-cached。
- Credentials:指是否與請(qǐng)求一起發(fā)送跨域 Cookie。它可以是include/same-origin/omit。
- Headers:可以包括與請(qǐng)求關(guān)聯(lián)的任何頭部, 例如HTTP 頭部這里顯示 “Content-Type”,但你也可以擁有自定義 HTTP 頭部。
- Redirect:決定了如果Fetch來的URL重定向會(huì)發(fā)生什么。它可以是follow/error/manual。
- referrerPolicy:確定請(qǐng)求傳遞的referrer信息量。它可以是 no-referrer/no-referrer-when-downgrade/origin/origin-when-cross-origin/same-origin/strict-origin/strict-origin-when-cross-origin/unsafe-url。
JavaScript:fetch,實(shí)現(xiàn)異步請(qǐng)求
當(dāng)我們使用 Fetch 時(shí),它會(huì)轉(zhuǎn)到我們定義的 URL,收集信息并將響應(yīng)返回。 這不是即時(shí)的,因?yàn)榧虞d URL 并將其取回需要時(shí)間。如果我們單獨(dú)運(yùn)行 Fetch,控制臺(tái)日志將返回一個(gè) Promise,而不是來自我們想要的 URL 的響應(yīng):
let apiResponse = fetch("https://fjolt.com/api");
console.log(apiResponse); // Returns Promise<Pending>
在fetch() 函數(shù)運(yùn)行時(shí),JavaScript并不會(huì)等待響應(yīng)。如果我們想要訪問響應(yīng),我們必須明確告訴 JavaScript 需要等待。
等待 fetch() 有兩種方法:
- 可以在 then 循環(huán)中使用 then 并操作 fetch() 的響應(yīng)。
- 可以使用 await,并在使用其內(nèi)容之前等待 Fetch 返回。
在 JavaScript 中使用 Then 等待Fetch
從fetch()調(diào)用中訪問數(shù)據(jù)的一種方法是將其鏈接到Fetch上,從而允許我們從URL訪問響應(yīng)。fetch()的內(nèi)容可以在then()回調(diào)函數(shù)內(nèi)操作,但不能在回調(diào)函數(shù)外操作。例如:
let apiResponse = fetch("https://fjolt.com/api").then(res => res.json()).then((data) => {
console.log(data);
// We can do anything with the data from our api here.
return data;
});
console.log(apiResponse); // This will return Promise<Pending>
// That means we can't use the apiResponse variable
// outside of the then() function.
如果我們想在 then 函數(shù)之外使用 fetch() 的內(nèi)容,則必須使用 await。
在 JavaScript 中使用 Await 等待Fetch
等待Fetch的另一種方法是使用 await 關(guān)鍵字。大多數(shù)的瀏覽器都支持Top-level awaits,如果你使用的是Node.JS 14.8 之前的版本,你需要將await相關(guān)的代碼打包到異步函數(shù)中。
如果我們使用 await,可以在函數(shù)或代碼的任何地方使用它來獲取 API 的響應(yīng),并在其上使用任何響應(yīng)函數(shù),例如 text() 或 json()。 例如:
// Typically we wrap await in an async function
// But most modern browsers and Node.JS support
// await statements outside of async functions now.
async getAPI() {
let apiResponse = await fetch("https://fjolt.com/api");
let response = apiResponse.json();
// Since we waited for our API to respond using await
// The response variable will return the response from the API
// And not a promise.
console.log(response);
}
getAPI();
結(jié)論
本文中,我們介紹了 Fetch 的工作原理、如何通過 fetch() 發(fā)送不同的選項(xiàng),以及如何使用 JavaScript 中的異步概念來等待響應(yīng)。 fetch() 是 JavaScript 中的一個(gè)強(qiáng)大工具,經(jīng)常在一些優(yōu)秀項(xiàng)目中發(fā)揮重要作用。
譯者介紹
陳豪,51CTO社區(qū)編輯,具有6年工作經(jīng)驗(yàn)的高級(jí)系統(tǒng)工程師。擅長技能有Linux內(nèi)嵌匯編語言,Python,C,C++,Java,Linux內(nèi)核分析,智能機(jī)器人軟件設(shè)計(jì)等。
原文標(biāo)題:??How Fetch Works in JavaScript??,作者:Johnny Simpson