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