天天看点

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)  // 请求
}