# fetch 介绍
fetch () 是一个全局方法,提供一种简单,合理的方式跨网络获取资源。它的请求是基于 Promise。
# fetch 使用语法
fetch(url,options).then((response)=>{ | |
// 处理 http 响应 | |
},(error)=>{ | |
// 处理错误 | |
}) |
- url:是发送网络请求的地址
- options:发送请求参数
- body: http 请求参数
- mode: 指定请求模式。
- 默认值为 cros: 允许跨域;
- same-origin: 只允许同源请求;
- no-cros: 只限于 get、post 和 head,并且只能使用有限的几个简单标头。
- cache: 用户指定缓存
- method:请求方法,默认 GET
- signal:用于取消 fetch
- header:http 请求头设置
- keepalive:用于页面卸载时,告诉浏览器后台保持连接,继续发送数据
- credentials:cookie 设置
- 默认 omit,忽略不带 cookie,
- same-origin 同源请求带 cookie
- inclue 无论跨域还是同源都会带 cookie
# response 对象
fetch 请求成功后,响应 response 对象:
- status:http 状态码,范围在 100-599 之间
- statusText:服务器返回状态文字描述
- ok:返回布尔值,如果状态码 2 开头的,则返回 true,反之 false
- headers:响应头
- body:响应体
- type:返回请求类型
- redirected:返回布尔值,表示是否发生过跳转
# 读取内容方法
response 对象根据服务器返回的不同类型数据,提供了不同的读取方法。分别有:
- response.text ():得到文本字符串
- response.json ():得到 json 对象
- respnse.blob ():得到二进制 blob 对象
- response.formData ():得到 fromData 表单对象
- response.arrayBuffer ():得到二进制 arrayBuffer 对象
# response.clone()
stream 对象只能读取一次,读取完就没了,这意味着,上边的五种读取方法,只能使用一个,否则会报错。因此 response 对象提供了 clone () 方法,创建 rsponse 对象副本,实现多次读取。如:将一张图片,读取两次:
const response1 = await fetch('flowers.jpg'); | |
const response2 = response1.clone(); | |
const myBlob1 = await response1.blob(); | |
const myBlob2 = await response2.blob(); | |
image1.src = URL.createObjectURL(myBlob1); | |
image2.src = URL.createObjectURL(myBlob2); |
# response.body()
body 属性返回一个 ReadableStream 对象,供用户操作,可以用来分块读取内容,显示下载的进度就是其中一种应用
const response = await fetch('flower.jpg'); | |
const reader = response.body.getReader(); | |
while(true) { | |
const {done, value} = await reader.read(); | |
if (done) { | |
break; | |
} | |
console.log(`Received ${value.length} bytes`) | |
} |
response.body.getReader() 返回一个遍历器,这个遍历器 read () 方法每次都会返回一个对象,表示本次读取的内容块
# 不同请求如何处理
请求方式不同,传值方式也不同。xhr 会分别处理 get 和 post 数据传输,还有请求头设置,同样 fetch 也需要分别处理。
# get 方式:
只需要在 url 中加入传输数据,options 中加入请求方式
<input type="text" id="user"><br> | |
<input type="password" id="pas"><br> | |
<button onclick="login()">提交</button> | |
<script> | |
function login(){ | |
fetch(`http://localhost:80/fetch.html?user=${user.value}&pas=${pas.value}`, { | |
method:'GET' | |
}).then(response=>{ | |
console.log('响应',response) | |
}) | |
} | |
</script> |
# post 方式:
使用 post 发送请求时,需要设置请求头、请求数据等
fetch(`http://localhost:80/ES6练习题/53fetch.html`, { | |
method:'POST', | |
headers:{ | |
'Content-Type':'application/x-www-form-urlencoded;charset=UTF-8' | |
}, | |
body:`user=${user.value}&pas=${pas.value}` | |
}).then(response=>{ | |
console.log('响应',response) | |
}) |
如果是提交 json 数据时,需要把 json 转换成字符串:
body: JSON.stringify(json) |
如果提交的是表单数据,使用 formData 转化:
body: new FormData(form) |
上传文件,可以包含在整个表单里一起提交:
const input = document.querySelector('input[type="file"]'); | |
const data = new FormData(); | |
data.append('file', input.files[0]); | |
data.append('user', 'foo'); | |
fetch('/avatars', { | |
method: 'POST', | |
body: data | |
}); |
上传二进制数据,将 blob 或 arrayBuffer 数据放到 body 属性里:
let blob = await new Promise(resolve => | |
canvasElem.toBlob(resolve, 'image/png') | |
); | |
let response = await fetch('/article/fetch/post/image', { | |
method: 'POST', | |
body: blob | |
}); |
# fetch 常见坑:
- 兼容性不好
- 默认不带 cookie,传 cookie 时,必须在 header 参数内加上
credenials:'include',才会像 xhr 将 cookie 带请求头中 - 异常处理需要手动实现