FetchAPI
FetchAPI是HTML5中新增的异步请求API,FetchAPI基于新的JavaScript语言标准和HTML5相关的API进行了重新设计,用于取代老旧的XMLHttpRequest
。FetchAPI和XHR的区别包括:
- 使用
Promise
实现异步操作 - 优化了API的设计,对HTTP请求的Request、Response、Headers等进行了合理拆分
有关兼容性,大多数现代浏览器都对FetchAPI有良好的支持,然而IE浏览器不支持FetchAPI,如果程序需要兼容IE浏览器则无法使用。
使用FetchAPI
由于FetchAPI是基于Promise
实现的,因此我们可以直接使用async/await
写法。下面例子中我们创建了一个异步函数,请求接口数据并解析JSON为对象后返回。
const fetchStudents = async function () {
try {
const rsp = await fetch('/students?classId=1', {
method: 'GET'
});
const rspData = await rsp.json();
return rspData;
} catch (e) {
console.log(e);
}
};
fetch()
函数接收两个参数:第1个参数一般为url字符串;第2个参数为可选的请求信息,包括请求方法、请求头、请求体数据等。
请求参数
URL请求参数
对于GET方式,我们需要通过URL来传递参数,FetchAPI对此没有特殊处理,我们需要拼接参数字符串。此时可以使用URLSearchParams
对象构造查询参数,该工具类可以自动处理参数拼接和URL编码。
const params = new URLSearchParams();
params.append('name', 'Tom');
params.append('age', '18');
console.log(params.toString());
输出:
name=Tom&age=18
具体fetch()
的使用前面已经介绍过,这里就不重复黏贴代码了。
JSON请求体
在接口的POST请求中,我们通常都是使用JSON传递请求参数,早期开发中还会用到XML的方式,但现在已经十分罕见了,这里我们只介绍JSON方式。例子如下:
const body = {
name: 'Tom',
age: 18
};
try {
const rsp = await fetch('/add', {
method: 'POST',
headers: {
'Content-type': 'application/json; charset=UTF-8',
},
body: JSON.stringify(body)
});
return await rsp.json();
} catch (e) {
console.log(e);
}
这里要注意,发起JSON请求时我们需要设置请求选项的body
参数,我们这里需要手动将对象序列化为JSON字符串;除此之外还需要设置Content-Type
请求头。
表单请求参数
对于POST方式,除了最常用的XML或JSON请求体方式传递参数,我们也可以使用表单格式传递请求参数,表单则又分为application/x-www-form-urlencoded
和multipart/form-data
两种方式。
application/x-www-form-urlencoded
application/x-www-form-urlencoded
和URL参数类似,也需要使用URLSearchParams
工具类进行构造,例子如下。
const body = new URLSearchParams();
body.append('name', 'Tom');
body.append('age', '18');
try {
const rsp = await fetch('/add', {
method: 'POST',
headers: {
'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
},
body
});
return await rsp.json();
} catch (e) {
console.log(e);
}
表单请求参数需要放在请求选项的body
字段中,发起请求时会自动转换为编码好的字符串,此外还需要注意的一点是我们需要正确设置请求的Header。
multipart/form-data
multipart/form-data
格式的表单一般用于内容较大的表单或是文件上传,此类型表单可以使用FormData
对象构造,例子如下。
const body = new FormData();
body.append('name', 'Tom');
body.append('age', '18');
try {
const rsp = await fetch('/add', {
method: 'POST',
body
});
return await rsp.json();
} catch (e) {
console.log(e);
}
这里要特殊注意,multipart/form-data
表单的请求头中需要带一个boundry
参数,作为这种特殊表单格式的字段边界,然而该参数一般是随机生成的。此处fetch()
的行为是,我们不需要设置任何Header,只需要设置body
参数为FormData
对象就可以了,发起请求时会自动识别并添加带boundry
的Content-Type
请求头。例如:
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary2wGx5u1ATsl53i4D
文件上传
HTTP协议下,浏览器端的文件上传一般也都基于multipart/form-data
格式的表单实现,其使用方法和上面文本表单相同。
const body = new FormData();
body.append('file', document.getElementById('file').files[0]);
对于大文件上传,我们也可以基于FileAPI对文件进行手动分片,然后通过FormData()
对象构造请求格式,具体使用FetchAPI上传的写法和之前相同,这里就不重复黏贴代码了。