Fetch API 概述
XMLHttpRequest的问题 1.所有的功能全部集中在同一个对象上,容易写出混乱不易维护的代码 2.采用传统的事件驱动方式,无法适配新的Promise API Fetch API的特点 1.并非取代AJAX,而是对AJAX传统API的改进 2.精细的功能分割:头部信息、请求信息、响应信息等均分不到不同的对象,更利于处理各种复杂的AJAX场景 3.使用Promis API,更利于异步代码的编写 4.Fetch API 并非ES6的内容,属于HTML5新增的Web API 5.需要掌握网络通信的知识
基本使用
使用fetch函数即可立即向服务器发送网络请求
参数
该函数有两个参数 1.必填,字符串,请求地址 2.选填,对象,请求配置 请求配置对象
-
method:字符串,请求方法,默认GET
-
headers:对象,请求头信息
-
body:请求体的内容,必须匹配请求头中的Content-Type
-
mode:字符串,请求模式
-
- cors:默认值,配置为该值,会在请求头中加入origin和referer
- no-cors:配置为该值,不会在请求头中加入origin和referer,跨域的时候可能出现问题
- same-origin:指示请求必须在同一个域中发生,如果请求其他域,则报错
-
credentials:如何携带凭据(cookie)
-
- omit:默认值,不携带cookie
- same-origin:请求同源地址的时候,携带cookie
- include:请求任何地址都携带cookie
-
cache:配置缓存模式
-
-
default:表示fetch请求之前检查一下http缓存
-
no-store:表示fetch请求将完全忽略http缓存的存在,这意味着请求之前将不再检查http的缓存,拿到响应后,他也不会更新http缓存
-
no-cache:如果存在缓存,那么fetch将发送一个条件查询requset和一个正常的request,拿到响应后,他会更新http缓存
-
reload:表示fetch请求之前将忽略http缓存的存在,但是拿到响应后,他主动更新http缓存
-
force-cache:表示fetch请求不顾一切的依赖缓存,即时缓存过期了,它依然从缓存中读取,除非没有任何缓存,那么它将发送一次正常的request
-
only-if-cached:表示fetch请求不顾一切的依赖缓存,即时缓存过期,他依然从缓存中读取,如果没有缓存,他将抛出网络错误(该设置只在mode为same-origin时有效)
-
返回值
fetch函数返回一个Promise对象
- 当收到服务器的返回结果后,Promise进入resolve状态,状态数据为Response对象
- 当网络发生错误(或者其他导致无法完成交互的错误)时,Promise进入rejected状态,状态数据为错误信息
Response对象
- ok:boolen,当响应码在200-299之间为true,其他为false
- status:number,响应的状态码
- text():用于处理文本格式的Ajax响应。他从响应中获取文本流,将其读完,然后返回一个被解决为string对象的Promis
- blob():用于处理二进制文件格式(比如图片或者电子表格)的Ajax响应。它读取文件的原始数据,一旦读取完整个我呢见,就返回一个被解决为blob对象的Promise
- json():用于处理JSON格式的Ajax响应。他将JSON数据流转换为一个被解决为JavaScript对象的Promise
- redirect():可用于重定向到另外一个URL。他会创建一个Promise,以解决来自重定向的URL的响应
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button>获取数据</button>
<script>
async function getProvince() {
const url = "http://example.com"
const config = {
method: 'GET'
}
const resp = await fetch(url, config)
const result = await resp.json()
console.log(result)
}
document.querySelector('button').onclick = function () {
getProvince()
}
</script>
</body>
</html>
Request 对象
除了使用基本的fetch方法 ,还可以通过创建一个Request对象来完成请求(实际上,fetch的内部会帮我们创建一个Request对象)
new Request(url地址, 配置)
注意点:
尽量保证每次请求都是一个新的Request对象
const request = new Request("https://www.mozilla.org/favicon.ico")
const url = request.url
const method = request.method;
const credentials = request.credentials;
fetch(request)
.then(resp => resp.blob())
.then(blob => {
image.src = URL.createObjectURL(blob)
})
const request = new Request("https://example.com", {
method: "POST",
body: '{"foo": "bar"}',
});
//备注: body 只能是一个 Blob、ArrayBuffer、TypedArray、DataView、FormData、URLSearchParams、ReadableStream 或 String 对象,也可以是一个字符串字面量,因此增加一个 JSON 对象的有效载荷则需要字符串化该对象。
Response对象
Response对象包含了很多属性和方法,也可以通过构造函数自定义该对象
const response = new Response()
Headers对象
Fetch API的Headers对象,允许你对HTTP请求头执行各种操作,包括检索、设置、添加、删除
使用Headers()构造方法创建一个新的Headers对象
const headers = new Heades({
"Content-Type":"image/jpeg"
})
Headers实例有很多方法
-
append()方法可以追加一个新值到已经存在的headers上,或者新增加一个原本不存在的header
-
const headers = new Headers() headers.append("Content-Type","image/jpeg") headers.get("Content-Type") //"image/jpeg" headers.append("a","1") headers.append("a","2") headers.get("a") // 1,2 -
delete()方法可以从当前Headers对象中删除指定标头
-
const headers = new Headers() headers.append("Content-Type","image/jpeg") headers.delete("Content-Type") headers.get("Content-Type")//null -
entries()方法以迭代器的形式返回Headers对象中所有键值对
-
const myHeaders = new Headers(); myHeaders.append("Content-Type", "text/xml"); myHeaders.append("Vary", "Accept-Language"); for (var pair of myHeaders.entries()) { console.log(pair[0] + ": " + pair[1]); } //content-type: text/xml //vary: Accept-Language -
has()方法判断当前Headers对象是否存在指定的标头
-
const myHeaders = new Headers(); myHeaders.append("Content-Type", "text/xml"); myHeaders.append("Vary", "Accept-Language"); myHeaders.has("Content-Type") //true myHeaders.has("a") //false -
keys()方法以迭代器的形式返回Headers对象中的所有key
-
const myHeaders = new Headers(); myHeaders.append("Content-Type", "text/xml"); myHeaders.append("Vary", "Accept-Language"); for (var key of myHeaders.keys()) { console.log(key); } //Content-Type //Vary -
set()方法可以在已经声明中的 Headers对象修改已有的一组键值对或者创建一个新的键值对,和append()方法不同的是,set对已经存在的key的值进行修改,append对已经存在的值是追加
-
var myHeaders = new Headers() myHeaders.append("Content-Type", "image/jpeg"); myHeaders.set("Content-Type", "text/html"); myHeaders.get("Content-Type") //text/html -
values()方法以迭代器的形式返回Headers对象中的所有value
-
const myHeaders = new Headers(); myHeaders.append("Content-Type", "text/xml"); myHeaders.append("Vary", "Accept-Language"); for (var value of myHeaders.values()) { console.log(value); } //text/xml //Accept-Language
文件上传
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="file">
<button>上传</button>
<img src="" alt="" style="width: 100px; height: 100px;">
<script>
async function upload() {
const input = document.querySelector("input")
if (input.files.length === 0) {
alert("请选择图片")
return
}
const formData = new FormData(); //构建请求体
formData.append("imagefile", input.files[0])
const url = 'http://example/upload'
const resp = await fetch(url, {
method: "POST",
body: formData////自动修改请求头
})
const result = await resp.json()
return result
}
document.querySelector('button').onclick = async function () {
const result = await upload();
const img = document.querySelector('img');
img.src = result.path
}
</script>
</body>
</html>