天天看點

fetchAPI

發送請求

要發送簡單的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)  // 請求
}