# ajax 请求与跨域相关知识点
# ajax, fetch, axios 「关注分离」
- 之前 IE 建立请求ActiveXObject('Microsoft.XMLHTTP')
- ajax 基于 XML 开发的,增加了对 JSONP 的支持,xhr = new XMLHTTPRequest(),下面为操作过程:
- open(method, url, boolean)启动一个请求
- send(null/data) 发生请求
- xhr对象的事件 onreqdystatechange, progress, abort, error, load, timeout
- xhr对象的属性readyState 0 未打开, 1已打开, 2已发送, 3正接收, 4完成
- xhr状态 200
- responseText, responseXML
- statusText
- 取消请求 abort()
- 需要监听onreqdystatechange事件,如果是完成状态,解析器 response 数据
- post 默认的 contentType 格式为 'application/x-www-form-urlencoded;charset=UTF-8'
- Axios 也是基于 XML 开发,不过是结合 promise 实现的,符合最新的 ES 规范
- 执行多个并发请求 axios.all(request1, request2)
- instance = axios.create(config) 或 axios.create() 对其修改默认配置 instance.defaults.timeout = 2500 或在请求时用参数的形式覆盖默认配置
- 对 node 与浏览器分别做了适配、支持
- 拦截请求和响应,myInterceptor = axios.interceptors.request.use()、axios.interceptors.response.use(then, catch); 移除:axios.interceptors.eject(myInterceptor) 或对实例添加拦截器:instance.interceptors.request.use()
- 取消请求
- 转换请求和响应数据,自动转换 JSON 数据
- 客户端支持XSRF
- 可以定义请求适配器
- Fetch API提供了一个 javascript 接口,用于访问 HTTP 管道部分,还提供了全局的 fetch()方法,返回一个 Promise 对象。是底层次的 API很容易被其他技术使用。已简单合理的方式来支持跨域。
- fetch不支持同步请求
- 只对网络请求报错,对 400、500都当做成功的请求,需要封装去处理。
- 默认不会带 cookie, 不支持 abort,不支持超时控制,使用setTimeout及Promise.reject的实现的超时控制并不能阻止请求过程继续在后台运行,造成了流量的浪费
- 没有办法原生检测请求的进度
- Response 限制了响应内容的重复读取和转换,因为数据流只能读取一次
// 请求参数
{
body?: any;
cache?: RequestCache;
credentials?: RequestCredentials; // 设置了才会带 cookie
headers?: HeadersInit;
integrity?: string;
keepalive?: boolean;
method?: string;
mode?: RequestMode;
redirect?: RequestRedirect;
referrer?: string;
referrerPolicy?: ReferrerPolicy;
window?: any;
}
window.fetch(url)
.then(response => {
// 通过 response.ok 判断 fetch 请求是否成功
// 请求结果是 response.body 是一个 ReadableStream
if (response.ok) {
//通过 response 原型上的 json 方法将 response.body 转换为 JS 对象,再返回出去
return response.json();
}
}
).then(result => {
console.log(result);
}).catch(error => {
console.log(error);
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 支持跨域请求的实现方案
- postMessage
- worker = new Worker(子线程jsPath) 主线程
- worker.postMessage()
- worker.onMessage
- 子线程:onmessage = ()=>{ postMessage()}
- Nginx 代理
- webSocket---connect, message, disconnect
- jsonp
- 利用script的url跨域特性, 发一个特殊的请求, 将函数名发送给后端, 后端返回相应的函数体
- jsonp【只能发送get请求, 无法更好的错误处理, 处理恶意攻击】, 反向代理, 图像ping【容易被缓存, 无法接到服务端的回复】, websocket【全双工】, CORS【需要后端配合】
- CROS
- Access-Control-Allow-Origin: 指定特定域名,跨域请求头就要带 Orign,否则没有;由于 CDN 缓存响应头Access-Control-Allow-Origin: xxx 已被缓存,另一个域请求就回出问题;此时需要 Vary:Origin 缓存不同的资源
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
- Access-Control-Allow-Credentials
- Access-Control-Expose-Headers
- Access-Control-Max-Age
- withCredentials
- Options 请求:不是简单请求,就回发送 OPTIONS 请求,项目中常见的
Content-Type: application/json及 Authorization: <token> 为典型的非简单请求,在发送请求时往往会带上 Options