fetch
https://caniuse.com/?search=fetch
https://developer.mozilla.org/zh-CN/docs/Web/API/fetch
const promise = fetch(url, [options]);Http 可以简单的分为两个阶段
- 获取 response header
- 获取 response body
fetch 的 response body 需要自己处理,如 .text() .json() .formData() .blob() .arrayBuffer()
fetch 的 response body 只能处理一次。
get
直接请求就是 GET
post
如下
const body = JSON.stringify({ hello: "world" });
let response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8",
},
body,
});header
请求头:
fetch(url, {
headers: {
Authentication: "secret",
},
});响应头
const response = await fetch(
"https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits"
);
response.headers.get("Content-Type"); // application/json; charset=utf-8响应头是一个类似 Map 的可迭代
for (let [key, value] of response.headers) {
//
}from data
如例:
let imageBlob = await new Promise((resolve) =>
canvasElem.toBlob(resolve, "image/png")
);
let formData = new FormData();
formData.append("firstName", "John");
formData.append("image", imageBlob, "image.png");
let response = await fetch("/article/formdata/post/image-form", {
method: "POST",
body: formData,
});from data 提供如下 api:
- formData.append(name, value) —— 添加表单字段,
- formData.append(name, blob, fileName) —— 添加一个 blob 字段。就像它是
<input type="file">。fileName 设置文件名而不是表单字段名。 - formData.delete(name) —— 删除
- formData.get(name) —— 获取
- formData.has(name) —— 是否存在。
abort
AbortController 可以关联多个 fetch,也就可以一口气请求多个。
let controller = new AbortController();
fetch(url, {
signal: controller.signal,
});
// 取消
controller.abort();单纯的取消 promise
let controller = new AbortController();
new Promise((resolve, reject) => {
// ... do something ...
controller.signal.addEventListener("abort", reject);
});config more
https://zh.javascript.info/fetch-api
referrer、referrerPolicy:HTTP 的 Referer header
mode cors | same-origin | no-cors 允许跨源请求|禁止跨源请求|只允许安全请求
credentials same-origin | include | omit
跨源不发送|总是发送|不发送
fetch 是否应该随请求发送 cookie 和 HTTP-Authorization header
cache default | no-store | reload | no-cache | force-cache | only-if-cached
?
redirect follow | error | manual
遵循 HTTP 重定向 | HTTP 重定向时报错 | 允许手动处理 HTTP 重定向
integrity hash 支持具体看浏览器,一般有 SHA-256,SHA-384,和 SHA-512
// 下载一个文件,使用 SHA-256 校验和为 “abcdef”
fetch("http://site.com/file", {
integrity: "sha256-abcdef",
});keepalive 请求在网页关闭后继续存在
一个简单的 fetch 封装
interface IGetPrams {
[key: string]: string | number | boolean;
}
/**
* URL 处理
*/
export const createURL = (
url: string,
config?: { param?: IGetPrams, base?: string }
) => {
const u = new URL(url, config?.base);
const param = config?.param;
if (param) {
for (const key of Object.keys(param)) {
const value = param[key];
u.searchParams.set(key, value + "");
}
}
return u;
};
type IHttpConfig = RequestInit & {};
/**
* post 请求
*
* 使用 response.json() 处理
*/
export const post = async (
url: string | URL,
data?: any,
config?: IHttpConfig
) => {
const u = typeof url === "string" ? createURL(url, { base: baseURL }) : url;
const headers = {
"Content-Type": "application/json;charset=utf-8",
};
if (config) {
const { headers: h } = config;
if (h) Object.assign(headers, h);
}
const response = await fetch(u, {
...config,
method: "POST",
headers,
body: JSON.stringify(data),
});
return response.json();
};
/**
* get 请求
*
* 使用 response.json() 处理
*/
export const get = async (
url: string | URL,
data?: IGetPrams,
config?: IHttpConfig
) => {
const u =
typeof url === "string"
? createURL(url, { base: baseURL, param: data })
: url;
const response = await fetch(u, {
...config,
});
return response.json();
};
export const setBaseURL = (url: string) => {
baseURL = url;
};
export const getBaseURL = () => baseURL;
let baseURL = "";