一、网络请求方式:
- AJAX:基于XMLHttpRequest收发请求,使用较为繁琐,代码量会比较多
- axios:基于promise的请求客户端,在浏览器和node中均可使用,使用便捷,功能强大
- fetch:内置api,基于promise,用法和axios类似,功能更为简单,没有axios那么强大
ajax一般为学习过渡使用,日常开发中一般不会使用。做项目的时候一般是使用axios,当项目规模比较小,调用接口次数很少的时候可以使用 fetch 替换 axios ,这样更为便捷迅速。
二、fetch介绍
该fetch介绍转自:前端人博客
1.1、fetch使用语法
javascript">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
- headers - http请求头设置
- keepalive - 用于页面卸载时,告诉浏览器在后台保持连接,继续发送数据。
- credentials - cookie设置,默认omit,忽略不带cookie,same-origin同源请求带cookie,inclue无论跨域还是同源都会带cookie。
1.2、response 对象
fetch 请求成功后,响应 response 对象如图:
- status - http状态码,范围在100-599之间
- statusText - 服务器返回状态文字描述
- ok - 返回布尔值,如果状态码2开头的,则true,反之false
- headers - 响应头
- body - 响应体。响应体内的数据,根据类型各自处理。
- type - 返回请求类型。
- redirected - 返回布尔值,表示是否发生过跳转。
1.3、读取内容方法
response 对象根据服务器返回的不同类型数据,提供了不同的读取方法。分别有:
- response.text() -- 得到文本字符串
- response.json() - 得到 json 对象
- response.blob() - 得到二进制 blob 对象
- response.formData() - 得到 fromData 表单对象
- response.arrayBuffer() - 得到二进制 arrayBuffer 对象
上述 5 个方法,返回的都是 promise 对象,必须等到异步操作结束,才能得到服务器返回的完整数据。
1.4、response.clone()
stream 对象只能读取一次,读取完就没了,这意味着,上边的五种读取方法,只能使用一个,否则会报错。
因此 response 对象提供了 clone() 方法,创建 respons 对象副本,实现多次读取。如下:将一张图片,读取两次:
javascript">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);
1.5、response.body()
body 属性返回一个 ReadableStream 对象,供用户操作,可以用来分块读取内容,显示下载的进度就是其中一种应用。
javascript">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() 方法每次都会返回一个对象,表示本次读取的内容块。
三、异步请求
fetch方法用于发起获取资源的请求,它返回一个promise,这个promise会在请求响应后被resolve,并传回request对象。fetch不支持同步请求,这意味着你不能像使用 XMLHttpRequest 那样直接在代码中执行同步请求。
fetch返回的数据不是即时的,因为加载 URL 并将其取回需要时间。如果我们单独运行 Fetch,控制台日志将返回一个 Promise,而不是我们想要的接口返回的响应:
javascript">// 假设后端接口为:https://www.example.com/api/get_user_info
// 该接口返回的数据为:{name:'张三',sex:'女',age:25}let apiResponse = fetch("https://www.example.com/api/get_user_info");
console.log(apiResponse); // 打印结果:Promise<Pending>1.2.3.
在fetch() 函数运行时,JavaScript并不会等待响应。如果我们想要访问响应,我们必须明确告诉 JavaScript 需要等待。
等待 fetch() 有两种方法:
- 可以在 then 循环中使用 then 并操作 fetch() 的响应。
- 可以使用 await,并在使用其内容之前等待 Fetch 返回。
在 JavaScript 中使用 Then 等待 Fetch
从fetch()调用中访问数据的一种方法是将其链接到Fetch上,从而允许我们从URL访问响应。fetch()的内容可以在then()回调函数内操作。
javascript">fetch('https://www.example.com/api/get_user_info').then(response => {if (!response.ok) {throw new Error('Network response was not ok');}return response.json(); // 将响应解析为 JSON 格式}).then(data => {// 处理返回的数据console.log(data);//打印结果:json数据{name:'张三',sex:'女',age:25}}).catch(error => {// 处理错误console.error('There was a problem with the fetch operation:', error);});
fetch()的内容可以在then()回调函数内操作,但不能在回调函数外操作。
javascript">let apiResponse = fetch("https://www.example.com/api/get_user_info").then(res => res.json()).then((data) => {//在这里处理数据是没问题的console.log(data); //打印结果:json数据{name:'张三',sex:'女',age:25}return data;});
console.log(apiResponse); //打印结果:Promise<Pending>
如果我们想在 then 函数之外使用 fetch() 的内容,则必须使用 await。
javascript">async function getAPI() {let apiResponse = await fetch("https://www.example.com/api/get_user_info");let response = await apiResponse.json(); //如果不用await,最终打印结果也会是:Promise<Pending>console.log(response); //打印结果:json数据{name:'张三',sex:'女',age:25}
}getAPI();
post提交
javascript">// form表单提交
fetch(`https://www.exaplem.com/api/save_user_info`,{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded;charset=UTF-8','Authorization': `Token ${login.token}`},body:`name=${user.name}&sex=${user.sex}&age=${user.age}`
}).then(response=>{console.log('响应',response)
})// 如果是提交json数据时,需要把json转换成字符串。如
// body:JSON.stringify(json)
// 如果提交的是表单数据,使用 formData转化下,如:
// body:new FormData(form)// 上传文件,可以包含在整个表单里一起提交,如:
// const data = new FormData();
// data.append('file', input.files[0]);
// data.append('user', 'foo');
// body:new FormData(form)// 上传二进制数据,将 bolb 或 arrayBuffer 数据放到body属性里,如:
let blob = await new Promise(resolve => canvasElem.toBlob(resolve, 'image/png')
);let response = await fetch('https://www.exaplem.com/api/save_user_portrait', {method:'POST',body:blob
});
四、注意事项
1、 fetch默认不带cookie
传递cookie时,必须在header参数内加上 credentials:'include',才会像 xhr 将当前cookie 带有请求中。
2、异常处理
fetch 不同于 xhr ,xhr 自带取消、错误等方法,所以服务器返回 4xx 或 5xx 时,是不会抛出错误的,需要手动处理,通过 response 中的 status 字段来判断