JavaScript Fetch API 與XMLHttpRequest一樣用於AJAX操作,但操作上更加直覺合理。
全局方法fetch將回傳Promise,且不管伺服器端回應狀態碼是否為200
都將會被以resolve
的方式處理,但回應body
將會帶有屬性ok
,其數值將會是false
或true
來表示請求是否成功。
/*
| fetch 是個全局方法,而不是建構子
*/
console.log(Fetch) // Fetch is not defined
console.log(window.fetch) // ƒ fetch() { [native code] }
/*
| fetch 接受 Request 物件作為參數
| 但也可以傳給他符合建構Request 物件的參數作為參數。
*/
// 這樣使用
const req = new Request(URL, {method: 'GET', cache: 'reload'})
fetch(req)
.then(res => console.log(res))
// 或是這樣
fatch(URL, {method: 'POST'})
.then(res => console.log(res))
了解到以上這個重點後就知道我們要了解的其實是Request建構子
Request建構子接受一個或兩個參數
第一個參數是URL,第二個參數則是可選的物件
const req = new Request('https://www.apple.com/ac/structured-data/images/knowledge_graph_logo.png?201709101434')
fetch(req)
.then(res => {
/*
| res 是個 Response 物件
| 必須將它轉為 blob, formData, json .. 等格式
*/
return res.blob()
})
.then(blob => {
/*
| 在這裡我們要將blob轉為圖片src
| 使用 URL.createObjectURL
*/
const img = new Image
// 允許跨域,確保可以正確用於 canvas
img.crossOrigin = 'anonymous'
// 將blob 轉為dataURL
img.src = URL.createObjectURL(blob)
// 將元素渲染至 body
document.body.appendChild(img)
})
在此範例中我們可以發現回傳值res
是個Response物件實例
我們無法直接使用,因此要將它轉為正確的資料格式,查看Response MDNMethods了解完整資訊
在Request物件中有一個屬性headers
headers
屬性接受一個鍵值對的物件
物件的操作本身雖然相當容易
但我們還是能夠以更聰明更可讀的方法來操作它,Headers物件
/*
| 實例化一個headers物件
| 接著我們就可以有幾個實用的方法
| Headers建構子接受一個選擇性物件的物件作為參數
| 我們可以直接定義headers需要的key與value
*/
const init = { '_token': 'hello12345world' }
const headers = new Headers(init)
console.log(headers.get('_token')) // hello12345world
/*
| has方法測試headers是否有屬性 test
*/
const hasToken = headers.has('_token')
console.log(hasToken) // true
const hasTest = headers.has('test')
console.log(hasTest) // false
/*
| get方法取得headers中指定屬性key的值
| 若指定key不存在則回傳 null
*/
const token = headers.get('_token')
console.log(token) // "hello12345world"
const token2 = headers.get('_token2')
console.log(token2)
/*
| set方法重設屬性的值
| 若指定key不存在則會新增至headers
*/
headers.set('_token2', 'it 30 days')
console.log(headers.get('_token2')) "it 30 days"
/*
| append方法為headers物件添加屬性
*/
headers.append('my-header', '1234567890')
console.log(headers.get('my-header')) // "1234567890"
/*
| keys 方法, 回傳所有headers物件的keys
| 可以簡單使用 for/of 迴圈枚舉
*/
for(let key of headers.keys()) {
console.log(key)
}
// _token
/*
| values() 方法, 回傳headers物件的values
| 可以簡單使用 for/of 迴圈枚舉
*/
for(let value of headers.values()) {
console.log(value)
}
// hello12345world
for(let prop of headers.entries()) {
const [key, value] = prop
console.log(key, value)
}
// _token hello12345world
fetch方法回傳Promise
且不管伺服器響應為何都將resolve一個Response實例
所以我們要使用Response物件所提供的方法
將回傳先轉成我們所需要的資料格式在做使用。
const req = new Request('https://www.apple.com/ac/structured-data/images/knowledge_graph_logo.png?201709101434')
fetch(req)
.then(res => {
console.log(res.constructor.name) // "Response"
return res.blob()
})
.then(imgBlob => {
const imgSrc = URL.createObjectURL(imgBlob)
const image = new Image
image.src = imgSrc
document.body.appendChild(image)
// 更多的處理 ...
})
這個範例展示了兩個重點
第一、fetch方法回傳的resolve
是個Response實例
第二、Response實例需要經過處理(例如範例中的.blob()
)才能真正被使用
完整的Response方法請參閱Response MDN文件
const headers = new Headers({
'_token': 'thisismytoken'
})
const formData = new FormData()
formData.append('email', 'example@mail.com')
const req = new Request('https://my/perfect/api.io', {
method: 'POST',
headers: headers,
body: formData
})
fetch(req)
.then(res => res.json())
.then(resJson => {
console.log(resJson)
// 做些什麼 ...
})
範例二表示了一個比較完整fetch
使用範例
範例中Request的屬性body
可以有多種類型,詳細請參閱Request MDN
本篇主要說明了全局方法fetch的使用方式,以及相關的幾個物件,希望有給大家一些想法。