發送請求
要發送簡單的HTTP請求,使用fetch()隻需要三步
1.調用fetch(),傳入要擷取内容的url
2.在http響應開始到達時取得第1步一步傳回的響應對象,然後調用這個響應對象的某個方法,讀取響應體
3.取得第2步異步傳回的響應體,按需處理他
fetch因為傳回promise通常要寫兩個then或兩個await,使用時通常要先把響應體解析成json對象,然後處了解析得到的對象
fetch("/api")
.then(response => response.json)
.then(currentUser =>{
displayUserInfo(currentUser)
})
HTTP狀态碼,響應頭,網絡錯誤
fetch()傳回的期約解決為一個Response對象。這個對象的status屬性是HTTP狀态碼,如表示成功的200或表示"Not Found"的404(statusText是狀态碼的英文描述),Response對象的ok屬性在狀态碼為200-299之間時是ture,其他情況為false。
當伺服器開始發送響應體時,fetch()隻要一收到HTTP狀态碼和響應頭就會解決他的期約,但此時通常還沒有收到完整的響應體。雖然響應體尚不完整,但已經可以在流程的第二部檢查頭部了。Response對象的headers屬性是一個Headers對象。使用它的has()方法可以測試某個頭部是否存在,使用它的get()方法可以取得某個頭部的值。HTTP頭部的名字是不區分大小寫的。
Headers對象是個可疊代對象,需要時可以疊代
fetch(url).then(response=>{
for(let [name, value] of response.headers){
console.log(`${name}:${value}`)
}
})
如果浏覽器響應了fetch()請求,那麼傳回的期約就會以一個Response對象兌現包括 404Not Found 和 500Internet Server Error 。
fetch()隻在聯系不到伺服器時才會拒絕傳回期約。如計算機斷網了,伺服器無法響應,URL的主機不存在等。因為這些錯誤任何網絡請求都可能發生,用catch可以捕獲到這些錯誤
上述流程未包含任何錯誤處理,如下為更接近實際的版本
fetch("/api")
.then(response =>{
if(response.ok && response.headers.get("Content-Type") === "application/json"){
return response.json()
} else {
throw new Error(`狀态碼${response.status}或Content-type出現錯誤`)
}
})
.then(currentUser => {
displayUserInfo(currentUser)
})
.catch(error=>{
console.log("Error:", error);
})
設定請求參數
通過url?可以傳遞query參數,或使用URL對象更友善的進行配置。
URL對象的searchParams屬性通過set、append等方法可以設定參數,詳見https://www.cnblogs.com/xt112233/p/15695779.html
async function search(term){
let url = new URL("/api/search")
url.searchParams.set("name", term)
let response = await fetch(url)
if(!response.ok) throw new Error(response.statusText)
let result = await response.json()
return result
}
解析響應體
Response對象擷取響應體除了有json()和text(),還有其他幾個方法
arrayBuffer
這個方法傳回一個期約,解決為一個ArrayBuffer。在響應包含二進制資料時,可以使用這個方法,基于得到的ArrayBuffer建立一個定型數組或一個DataView對象,再讀取二進制資料。
formData
這個方法傳回一個期約,解決為一個formData對象。如果響應體是以multipart/form-data格式編碼的,應該使用這個方法。formData常用于post請求中,響應不太常見。
指定請求方法和請求體
通過配置項可以設定請求方法、請求體、請求頭等參數
fetch(url,{
method:"POST",
headers: new Headers({"Content-Type": "application/json"}),
body: JSON.stringify({a:1, b:2})
})
中斷請求
可以使用AbortController對象中斷某個fetch請求,這個控制器對象的signal屬性是一個AbortSignal對象。在fetch的配置項中,可以将這個對象以signal屬性的值傳進去,然後在想中斷的時候調用控制器對象的abort()。可以使與該請求相關的任何期約對象以一個異常被拒絕。
示例:
function fetchWithTimeout(url, options = {}){
// 對fetch進行了一層封裝,若有逾時屬性且請求逾時,中斷請求
if(options.timeout){ // 如果有逾時屬性,執行
let controller = new AbortController() // 建立控制器
options.signal = controller.signal // 将控制器的signal屬性傳入配置項
setTimeout(()=>{ // 若請求完成前執行定時器,則中斷,請求完成後執行無影響
controller.abort()
}, options.timeout)
}
return fetch(url, options) // 請求
}