# Ajax
# 介绍
网络请求是网页开发的必经环节,其中有一些问题我们需要重点关注:
- 请求能否正常返回,如果非正常返回或发生错误该如何处理
- 请求是否跨域,如何解决跨域
- 我们是否能监控所有请求,保证接口和页面显示的稳定
- 调用网络请求的方式难以统一,甚至存在冗余的函数定义 解决这些问题就是封装该模块的初衷
# 功能
- 能够满足任意请求目标,常用浏览器环境下的网络请求
- 能够解决跨域问题
- 能够监控请求,上报错误和异常情况
- 以统一的调用方式,返回处理方式,标准化解决请求异常
# 特点
- 简单,易上手
- 灵活,支持广
- 返回处理标准统一,上报使得可追踪,出现问题易定位
# 更新日志
2020.11.5
- jFetch的formdata提交优化
- 新增顺序和同时加载多个 js 的方法
# 安装
默认存在
# 使用
# 通用请求
【jFetch】
基于浏览器原生的 fetch API,涉及参数的详细介绍如下
参数 | 类型 | 含义 |
---|---|---|
method | string | 请求类型,GET(默认值)/HEAD/POST/PUT/DELETE/OPTIONS/PATCH |
mode | string | 用于指定处理特定类型的请求,same-origin/cors(默认值)/no-cors |
cache | string | 请求与内核 HTTP cache 交互的模式,default(默认值)/no-cache/no-store/reload/force-cache/only-if-cached |
credentials | string | 请求的凭据指定,include/same-origin(默认值)/omit |
redirect | string | 重定向时的选项,follow(默认值)/error/manual |
referrer | string | 请求来源的 header,client(默认值)/no-referrer/空 |
各参数相关的详细说明:
# mode
- same-origin 只处理同源请求
- cors 表示同域或者带有恰当 CORS 响应头(服务端支持 cors)的跨域下可请求成功. 其他请求将被拒绝
- no-cors 常用于跨域请求服务器不带 CORS 响应头场景
# cache
- default — 默认情形,内核会以下面方式使用 HTTP cache:
如果命中 HTTP cache 并且资源是 fresh 的,会直接使用 cache。 如果命中 HTTP cache 并且资源是 stale 的,内核会发起条件请求,如果服务器回应资源未有修改,则直接使用 cache,否则会下载资源和更新 cache。 如果没有命中 HTTP cache,内核会发起普通请求,下载资源和更新 cache。
- no-store — 内核忽略 HTTP cache,直接向服务器请求资源,资源下载成功后也不会更新 HTTP cache。
- reload — 内核忽略 HTTP cache,直接向服务器请求资源,但资源下载成功后会更新 HTTP cache。
- no-cache — 内核会以下面方式使用 HTTP cache:
如果命中 HTTP cache 并且资源是 fresh/stale 的,内核会发起条件请求,如果服务器回应资源未有修改,则直接使用 cache,否则会下载资源和更新 cache。 如果没有命中 HTTP cache,内核会发起普通请求,下载资源和更新 cache。
- force-cache — 内核会以下面方式使用 HTTP cache:
如果命中 HTTP cache 并且资源是 fresh/stale 的,会直接使用 cache。 如果没有命中 HTTP cache,内核会发起普通请求,下载资源和更新 cache。
- only-if-cached — 内核会以下面方式使用 HTTP cache:
如果命中 HTTP cache 并且资源是 fresh/stale 的,会直接使用 cache。 如果没有命中,会返回错误。 这个模式只允许在 Request.mode = "same-origin"时使用。
# credentials
- include:任何时候都带上凭据;
- same-origin:只在同源时允许带凭据(默认);
- omit:任何时候都不带
# referrer
- 可以设定为'',则不发送 referrer
- 或者设定为同源下的其他链接
- 默认是当前链接
返回 | 类型 | 含义 |
---|---|---|
请求状态 | Promise | 在 then 中执行成功的回调,catch 中执行失败回调 |
以下列举一些常见的使用栗子
# AutoCMS 请求(跨域 Get)
AutoCMS 的返回多是 content-type:application/x-javascript,需做特殊处理
let url = '//lol.qq.com/act/AutoCMS/publish/LCU/SubNav/subnav.js';
Ajax.jFetch({
url,
})
.then((raw) => {
// 针对autoCMS类型,可以进行过如下处理得到JSON数据
eval(raw);
let data = window.SubNav;
delete window.SubNav;
console.log(data);
})
.catch((e) => {
console.log(e);
});
2
3
4
5
6
7
8
9
10
11
12
13
14
# Post 请求
let postUrl = '';
Ajax.jFetch({
url: postUrl,
method: 'POST',
body: {
param1: 'xxx',
param2: 'xxx',
},
})
.then((data) => {
console.log(data);
})
.catch((e) => {
console.log(e);
});
//form表单提交1,
//提交是payload不是formdata的情况,导致提交不成功时
Ajax.jFetch({
url: postUrl,
method: 'POST',
credentials: 'include',//传登录态
headers: {// 浏览器原生的form表单,请求体中的数据会以普通表单形式(键值对)发送到后端
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'key1=value1&key2=value2'
}).then((data) => {
console.log(data);
}).catch((e) => {
console.log(e);
})
//formData的表单提交2
let formDataObj = new FormData();
formDataObj.append("age", 1);
formDataObj.append("name", 'XXXX');
Ajax.jFetch({
url: postUrl,
method: 'POST',
credentials: 'include',
body: formDataObj
}).then((res) => {
console.log(res);
}).catch((e) => {
console.log(e);
})
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 普通 Get 跨域请求
let url = '//lol.ams.game.qq.com/lol/live/v1/anchor';
Ajax.jFetch({
url,
})
.then((data) => {
console.log(data);
})
.catch((e) => {
console.log(e);
});
2
3
4
5
6
7
8
9
10
# JSONP
【jsonp】
可用于专门支持 fetch 无法解决的场景,如跨域且服务端不支持 cors,且服务器支持 jsonp,使用场景如下
# 服务端不支持 cors
此时如果使用 fetch,会有以下两种情况,都不能得到结果:
- mode: cors;该设定在跨域情况下,必须服务端支持 cors,能够返回正确的 cors 头,如 Access-Control-Allow-Origin 等。但如服务端不支持 cors 是不能返回正确的 cors 的 header 头的。往往产生如下报错: xxxx has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
- mode: no-cors;可以设置改模式来应对服务器不支持 cors 的情况;该模式允许浏览器发送本次跨域请求,但是不能访问响应返回的内容,这也是其 response type 为 opaque 透明的原因。
let url = `//lol.sw.game.qq.com/lol/commact/?proj=a20200415livelink&c=a20200415livelink&a=getMatchScheduleList`;
Ajax.jsonp(url)
.then((data) => {
console.log(data);
})
.catch((e) => {
console.log(e);
});
2
3
4
5
6
7
8
# 加载 js
【loadJS】
解决服务器不支持 CORS,且不支持 JSONP 的情况。
JSONP 要求服务器的响应为 json 数据的包装(故称之为 jsonp,即 json padding),形如:callback({"name":"hax","gender":"Male"})
# 直接加载 js 文件
let url = '//lpl.qq.com/web201612/data/LOL_MATCH2_TEAM_LIST.js';
Ajax.loadJS(url)
.then((data) => {
console.log(data);
// undefined
console.log(TeamList);
// xxx 全局变量
})
.catch((e) => {
console.log(e);
});
2
3
4
5
6
7
8
9
10
11
由于该 js 文件返回的是全局变量,并没有数据返回,获取数据要么直接访问全局变量,要么可以通过以下操作得到 json 数据
let url = '//lpl.qq.com/web201612/data/LOL_MATCH2_TEAM_LIST.js';
Ajax.loadJS(url, { dataName: 'TeamList' })
.then((data) => {
console.log(data);
})
.catch((e) => {
console.log(e);
});
2
3
4
5
6
7
8
# 顺序加载 js 文件
注意如果不传charset
参数,则默认是utf-8
当脚本具有依赖关系时使用
let urls = [
{
src:'//ossweb-img.qq.com/images/js/milo_bundle/milo.js',
charset:'utf-8'
},
{
src:'https://ossweb-img.qq.com/images/js/PTT/ping_tcss_tgideas_https_min.js',
charset:'utf-8'
}
];
Ajax.seriesLoadScripts(urls)
.then((data)=>{
console.log('都加载完了');
console.log(data);
})
.catch((e)=>{
console.log(e);
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 并行加载 js 文件
注意如果不传charset
参数,则默认是utf-8
当脚本相互独立运行时推荐使用
let urls = [
{
src:'//ossweb-img.qq.com/images/js/milo_bundle/milo.js',
charset:'utf-8'
},
{
src:'https://ossweb-img.qq.com/images/js/PTT/ping_tcss_tgideas_https_min.js',
charset:'utf-8'
}
];
Ajax.parallelLoadScripts(urls)
.then((data)=>{
console.log('都加载完了');
console.log(data);
})
.catch((e)=>{
console.log(e);
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18