JavaScript fetch 快速入門
- fetch API 簡介
- fetch 的浏覽器支援情況
- 使用fetch
- 一個最簡單的fetch
- 在浏覽器中用fetch擷取資料
- 用fetch和POST方法送出表單
- 參考
fetch API 簡介
ECMAScript 2015(ES6) 标準的釋出已經三年有餘,現代浏覽器對ES6文法的支援趨于完善,用Promise對象處理異步請求被越來越多的開發者應用。為了更好地處理異步請求,作為對現有的
XMLHttpRequest
方法的替代,JavaScript引入了
fetch
方法,基于Promise處理異步請求。
更多關于fetch的介紹,可以參考MDN關于fetch的介紹。
這篇文章假設你具備:
- 有JavaScript基礎
- 對Promise對象有了解
如果你想了解Promise的相關知識,可以參考阮一峰老師的書籍
fetch 的浏覽器支援情況
參考Can I Use,下圖為本文寫作時間(2018年12月14日)的支援情況,點選這裡檢視最新的支援情況
可以看到目前全球範圍内支援已經達到87.84%,在中國也有69.65%的支援,并且将來這個資料必然會繼續升高,已經廣泛地被主流浏覽器所支援(IE除外)。
使用fetch
fetch接受兩個參數,
url
和
init
,其中
url
參數是必須的,而
init
參數是可選的。
url
參數是一個字元串,表示請求的url位址,而
init
是一個對象,在裡面可以對這個請求進行配置,例如設定請求方法,設定請求頭等,如果不傳入
init
參數,将會采用預設的配置,可以點選這裡檢視MDN文檔對fetch第二個參數的說明以及預設配置。
傳回一個包含
Promise
對象,在這個對象的
resolve
方法中可以通路到請求的結果,是一個
Response
對象,可以點選這裡檢視MDN文檔對Response對象的屬性和方法的具體說明。
你無須對fetch的配置以及
Response
十分熟悉,也可以友善地使用fetch,使用預設的配置即可完成很多工作,當你有特定需求時再回過頭來了解細節即可,接下來我們來寫一個最簡單的fetch。
一個最簡單的fetch
讓我們來寫一個最簡單的fetch,從伺服器上擷取一個json檔案并列印出來,我将一個簡單的JSON檔案上傳到了我的GitHub上,你可以點選這裡檢視它。
這個JSON檔案是這樣的:
[
{
"name": "張三",
"age": 18
},
{
"name": "李四",
"age": 20
},
{
"name": "王五",
"age": 22
}
]
現在我們用fetch擷取這個檔案,并把它列印出來,要知道,fetch預設使用的是
GET
方法,是以在這裡我們不需要第二個參數就可以達到我們的目的。
fetch('https://raw.githubusercontent.com/DaKoala/fetch-example/master/people.json')
.then(res => res.json())
.then(json => console.log(json))
// [{ name: "張三", age: 18 }, { name: "李四", age: 20 }, { name: "王五", age: 22 }]
請注意,這裡我們調用了
then
方法2次,在第一個
then
中,我們得到了一個
Response
對象,我們調用它的
.json()
方法,來擷取伺服器響應中的資料,需要注意的是,
res.json()
傳回的是一個
Promise
對象,而不是JSON化的資料,參考MDN文檔中的說明:
在這裡,
res.json()
傳回了一個
Promise
對象,在這個
Promise
對象的
then
方法中我們可以通路到被解析成JSON格式的資料,這時候我們才可以使用這些資料,是以要一個Promise鍊,總共調用兩次
then
方法。
如果你喜歡最新的
async/await
文法,我們也可以換一種風格完成同樣的事情,就像這樣:
(async () => {
const res = await fetch('https://raw.githubusercontent.com/DaKoala/fetch-example/master/people.json');
const json = await res.json();
console.log(json);
// [{ name: "張三", age: 18 }, { name: "李四", age: 20 }, { name: "王五", age: 22 }]
})();
由于
await
關鍵詞隻能在
async
函數中出現,是以我在這裡寫了一個包含
async
關鍵詞的立即執行函數表達式(IIFE),這個代碼的效果與上文出現的
Promise
風格的代碼一緻。
如果你想了解
async/await
相關的知識,可以參考阮一峰老師的書籍。
在浏覽器中用fetch擷取資料
讓我們繼續使用剛才的JSON檔案,這次我們在浏覽器中進行同樣的操作,并将結果加進HTML中,也就是說,我們用fetch進行一個AJAX請求。
HTML檔案
<h1>Fetch示例</h1>
<div id="container"></div>
JavaScript檔案
function fetchClassic() {
fetch('https://raw.githubusercontent.com/DaKoala/fetch-example/master/people.json')
.then(res => res.json())
.then(json => {
const container = document.getElementById('container');
json.forEach(item => {
const element = document.createElement('p');
element.textContent = `${item.name} - ${item.age}歲`;
container.appendChild(element);
});
});
}
fetchClassic();
如果你喜歡
async/await
風格,你可以這樣寫:
async function fetchAsync() {
const res = await fetch('https://raw.githubusercontent.com/DaKoala/fetch-example/master/people.json');
const json = await res.json();
const container = document.getElementById('container');
json.forEach(item => {
const element = document.createElement('p');
element.textContent = `${item.name} - ${item.age}歲`;
container.appendChild(element);
});
}
fetchAsync();
運作結果(兩種風格的JavaScript代碼結果是一樣的):
你可以在CodePen上看到這段代碼的實際運作效果,并自己動手嘗試一下。
用fetch和POST方法送出表單
接下來我将簡短地介紹一下用fetch和HTTP POST方法來送出表單到伺服器的方法,與上一個例子不同的是,我們這次要用到fetch的第二個參數來配置一下我們的請求。讓我們假定送出表單的位址為
https//example.billyzou.com/post
,在實際使用中,請把這個位址改成你伺服器的位址。由于我們要用
POST
方法而預設的方法為
GET
,是以我們需要手動配置請求方法,同時我們還要在請求頭中加上
Content-Type
字段,這個字段的值要與請求體中的資料格式相同。
如果我們用JSON的形式送出表單:
const data = { name: 'Billy', age: 18 };
fetch('https//example.billyzou.com/post', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringfy(data), // "{"name":"Billy","age":18}"
})
如果我們用form的格式送出表單:
const data = { name: 'Billy', age: 18 };
function formatData(data) {
const result = Object.entries(data).map(([key, value]) => `${key}=${value}`).join('&');
return result;
}
fetch('https//example.billyzou.com/post', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formatData(data), // "name=Billy&age=18"
})
注意兩種方法中由于資料格式不同,請求頭中的
Content-Type
字段對應被設定為了
application/json
和
application/x-www-form-urlencoded
,在實際操作時請根據你的選擇來設定對應的請求頭,以便伺服器能正确地接收資料。
參考
- Mozilla Developer Network
歡迎大家通路我的GitHub首頁來與我進行交流,位址是https://github.com/DaKoala