fetch
核心接口:
- fetch()
- Response
- Request
- Headers
使用场景:
1. 抓取图片和上传图片
// 图片抓取
let response = await fetch(url, options);
let blob = await response.blob();
// 使用a标签承载下载功能
----------------------
// canvas绘图发送至服务器
canvasElem.toBlob((blob) => {
fetch('xxxx', { method: 'POST', body: blob })
.then(response => response.json())
.then(result => alert(JSON.stringify(result, null, 2)))
}, 'image/png');
读取fetch响应结果的几种方式:
response.text()—— 读取 response,并以文本形式返回 responseresponse.json()—— 将 response 解析为 JSON 格式response.formData()—— 以 FormData 对象的形式返回 responseresponse.blob()—— 以 Blob(具有类型的二进制数据)形式返回 responseresponse.arrayBuffer()—— 以 ArrayBuffer(原始的二进制数据)形式返回 responseresponse.clone()—— 创建副本,实现多次读取
2. 跟踪下载进度
监听上传进度使用xhr; axios可用于监听上传、下载进度
使用api: typedArray + ReadableStream + blob/TextDecoder
const response = await fetch(xxxx);
const reader = response.body.getReader(); // 创建流读取器
const binaryChunks = []; // 存储二进制数据块
let receivedLength = 0;
/* 计算数据块的总字节长度*/
const contentLength = response.headers.get('Content-Length');
/* 分块读取数据 */
while(true) {
// value为读取的数据块
const {done, value} = await reader.read();
if (done) {
break;
}
binaryChunks.push(value);
receivedLength += value.length;
}
/* 解析数据*/
// 使用类型化数组合并二进制数据块chunks, 并解码为字符串
let chunksAll = new Uint8Array(receivedLength);
let position = 0;
for(let chunk of binaryChunks) {
chunksAll.set(chunk, position);
position += chunk.length;
}
const result = new TextDecoder("utf-8").decode(chunksAll);
const commits = JSON.parse(result);
// 或者生成blob对象
const blob = new Blob(binaryChunks)
3. 中止请求
// 同时中止fetch请求与其他异步请求
let urls = [...];
let controller = new AbortController();
let ourJob = new Promise((resolve, reject) => {
// 我们的任务
...
controller.signal.addEventListener('abort', reject);
});
let fetchJobs = urls.map(url => fetch(url, { signal: controller.signal }));
let results = await Promise.all([...fetchJobs, ourJob]);
// controller.abort() 被从任何地方调用
// 它都将中止所有 fetch 和 ourJob
4. keepalive
用户离开网页时,脚本向服务器提交一些用户行为的统计信息
window.onunload = function() {
fetch('/analytics', {
method: 'POST',
body: "statistics",
keepalive: true // 页面卸载时,保持连接继续发送数据
});
};
fetch与xhr区别:
- fetch基于promise实现
- fetch采用模块化设计,api分散在多个对象上
- fetch通过数据流(Stream 对象)处理数据,可以分块读取,有利于提高网站性能表现,对于请求大文件或者网速慢的场景相当有用; 例如视频缓冲区、图像逐步加载显示
- fetch监听下载进度,ajax跟踪上传进度
跨域处理
主流的跨域解决方案:CORS
// 跨域请求分为安全请求、非安全请求
// 安全请求(get、post等简单请求)
后台配置:
- Access-Control-Allow-Origin
// 非安全请求(patch、delete等请求或者携带特殊的请求头), 请求之前会进行预检请求(preflight)
1. 预检请求
请求头配置:
- Access-Control-Request-Method: xxx
- Access-Control-Request-Headers: xxx
预检响应:
- Access-Control-Allow-Origin: xxx
- Access-Control-Allow-Methods: xxx
- Access-Control-Allow-Headers: xxx
- Access-Control-Max-Age:xxx // 缓存预检权限, 保证后续请求不触发预检
2. 实际请求发出
// fetch支持跨域
fetch(url, { mode: 'cors' })
在service worker中使用
参考链接: Stream_Api、 跨域--Fetch、 常见的跨域解决方案、 service worker