🥇 Axios
链接:http://www.axios-js.com/
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
安装:npm install axios
尚硅谷_axios从入门到源码分析.doc
🥇 特性
从浏览器中创建 XMLHttpRequests
从 node.js 创建 http 请求
支持 Promise API
拦截请求和响应
转换请求数据和响应数据
取消请求
自动转换 JSON 数据
支持批量发送多个请求
客户端支持防御 XSRF
🥇 前后台交互的基本过程
1. 前后应用从浏览器端向服务器发送HTTP请求(请求报文)
2. 后台服务器接收到请求后, 调度服务器应用处理请求, 向浏览器端返回HTTP响应(响应报文)
3. 浏览器端接收到响应, 解析显示响应体/调用监视回调
🥇 HTTP 请求报文
1. 请求行: 请求方式/url
2. 多个请求头: 一个请求头由name:value组成, 如Host/Cookie/Content-Type头
3. 请求体
🥇 HTTP 响应报文
1. 响应行: 响应状态码/对应的文本
2. 多个响应头: 如 Content-Type / Set-Cookie 头
3. 响应体
🥇 url 上的 2 种请求参数
query 参数:
路由path: /xxx
请求path: /xxx?username=xxx&password=yyy
获取参数: req.query.username / req.query.password
params 参数:
路由path: /xxx/:username/:password
请求path: /xxx/xxx/123
获取参数: req.params.username / req.params.password
🥇 常见响应状态码
200 OK 请求成功。一般用于GET与POST请求
201 Created 已创建。成功请求并创建了新的资源
401 Unauthorized 未授权/请求要求用户的身份认证
404 Not Found 服务器无法根据客户端的请求找到资源
500 Internal Server Error 服务器内部错误,无法完成请求
🥇 不同类型的请求及其作用:
1. GET: 从服务器端读取数据
2. POST: 向服务器端添加新数据
3. PUT: 更新服务器端已经数据
4. DELETE: 删除服务器端数据
🥇 API 的分类
1. REST API: restful
发送请求进行CRUD哪个操作由请求方式来决定,增删改查(CRUD)
同一个请求路径可以进行多个操作
请求方式会用到GET/POST/PUT/DELETE
2. 非 REST API: restless
请求方式不决定请求的CRUD操作,增删改查(CRUD)
一个请求路径只对应一个操作
一般只有GET/POST
测试: 可以使用 json-server 快速搭建模拟的 rest api 接口
🥇 axios 的特点
基于 promise 的封装 XHR 的异步 ajax 请求库
浏览器端 node 端,都可以使用
支持请求/响应拦截器
支持请求取消
请求/响应数据转换
批量发送多个请求
🥇 axios 返回值解析
config - 请求配置
data - 响应体, 返回结果 ( 返回结果会自动解析 json 数据为一个对象 )
headers - 相应头信息
request - 原生的 AJAX 请求对象
status - 响应的状态码
statusText - 响应的字符串
🥇 axios 常用语法以及使用
🥈 请求配置
这些是创建请求时可以用的配置选项。只有 url 是必需的。如果没有指定 method,请求将默认使用 get 方法。
{
// url 是用于请求的服务器 URL
url: '/user',
// method 是创建请求时使用的方法
method: 'get',
/**
* 如果没有配置 method 默认就是 get
* method 常见的可选值为 get / post / put / delete
*/
// baseURL 将自动加在 url 前面,除非 url 是一个绝对 URL
// 比如这里的请求地址就是: https://www.baidu.com/api/user
// 它可以通过设置一个 baseURL 便于为 axios 实例的方法传递相对 URL
baseURL: 'https://www.baidu.com/api/',
// transformRequest 允许在向服务器发送前,修改请求数据
// 只能用在 PUT, POST 和 PATCH 这几个请求方法
// 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
transformRequest: [function (data, headers) {
// 对 data 进行任意转换处理
return data;
}],
// transformResponse 在传递给 then/catch 前,允许修改响应数据
transformResponse: [function (data) {
// 对 data 进行任意转换处理
return data;
}],
// headers 是即将被发送的自定义请求头
headers: {'X-Requested-With': 'XMLHttpRequest'},
headers: {'Content-Type':'application/x-www-form-urlencoded'},
headers: {'Content-Type':'multipart/form-data'}
// paramsSerializer 是一个负责 params 序列化的函数
// (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
paramsSerializer: function(params) {
return Qs.stringify(params, {arrayFormat: 'brackets'})
},
// params 是即将与请求一起发送的 URL 参数
// params 是添加到 url 的请求字符串中的,用于 get 请求。
// 必须是一个无格式对象 (plain object) 或 URLSearchParams 对象
params: {
ID: 12345
},
// data 是作为请求主体被发送的数据
// data 是添加到请求体(body)中的, 用于post请求。
// 只适用于这些请求方法 PUT, POST, 和 PATCH
// 在没有设置 transformRequest 时,必须是以下类型之一:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - 浏览器专属:FormData, File, Blob
// - Node 专属: Stream
data: {
name: 'chen'
},
// timeout 指定请求超时的毫秒数 (0 表示无超时时间)
// 如果请求话费了超过 timeout 的时间,请求将被中断
timeout: 1000,
// withCredentials 表示跨域请求时是否需要使用凭证
withCredentials: false, // default
// adapter 允许自定义处理请求,以使测试更轻松
// 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
adapter: function (config) {
/* ... */
},
// auth 表示应该使用 HTTP 基础验证,并提供凭据
// 这将设置一个 Authorization 头,覆写掉现有的任意使用 headers 设置的自定义 Authorization 头
auth: {
username: 'janedoe',
password: 's00pers3cret'
},
// responseType 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
responseType: 'json', // default:json
// responseEncoding 表示用于解码响应的编码
// 注意:忽略 "responseType" 或客户端请求的 "responseType"
responseEncoding: 'utf8', // default:utf8
// xsrfCookieName 是用作 xsrf token 的值的 cookie 的名称
xsrfCookieName: 'XSRF-TOKEN', // default:XSRF-TOKEN
// xsrfHeaderName 是携带 xsrf 令牌值的 http 标头的名称
xsrfHeaderName: 'X-XSRF-TOKEN', // default:X-XSRF-TOKEN
// onUploadProgress 允许为上传处理进度事件
onUploadProgress: function (progressEvent) {
// 使用本机进度事件做任何你想做的事
},
// onDownloadProgress 允许为下载处理进度事件
onDownloadProgress: function (progressEvent) {
// 对原生进度事件的处理
},
// maxContentLength 定义允许的响应内容的最大尺寸
maxContentLength: 2000,
// validateStatus 定义对于给定的 HTTP 响应状态码是 resolve 或 reject promise 。如果 validateStatus 返回 true (或者设置为 null 或 undefined ),promise 将被 resolve; 否则,promise 将被 rejecte
validateStatus: function (status) {
return status >= 200 && status < 300; // default
},
// maxRedirects 定义在 node.js 中 follow 的最大重定向数目
// 如果设置为0,将不会 follow 任何重定向
maxRedirects: 5, // default
// socketPath 定义了一个在 node.js 中使用的 UNIX 套接字。
// 例如 '/var/run/docker.sock' 向 docker 守护进程发送请求。
// 只能指定 socketPath 或 proxy。
// 如果两者都指定,则使用 socketPath。
socketPath: null, // default
// httpAgent 和 httpsAgent 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。允许像这样配置选项:
// keepAlive 默认没有启用
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }),
// proxy 定义代理服务器的主机名称和端口
// auth 表示 HTTP 基础验证应当用于连接代理,并提供凭据
// 这将会设置一个 Proxy-Authorization 头,覆写掉已有的通过使用 header 设置的自定义 Proxy-Authorization 头。
proxy: {
host: '127.0.0.1',
port: 9000,
auth: {
username: 'mikeymike',
password: 'rapunz3l'
}
},
// cancelToken 指定用于取消请求的 cancel token
cancelToken: new CancelToken(function (cancel) {
})
}
🥈 请求
// 通用请求
axios({
method: "GET", // 请求方式
url: "http://localhost:3000/student", // URL
params: { // url 后的参数
ID: 12345
},
}).then((response) => {
console.log(response);
});
// 发送 GET 请求(默认的方法)
axios(url);
// 请求方法的别名
// 为方便起见, 为所有支持的请求方法提供了别名
// axios.request(config)
// axios.get(url[, config])
// axios.delete(url[, config])
// axios.head(url[, config])
// axios.options(url[, config])
// axios.post(url[, data[, config]])
// axios.put(url[, data[, config]])
// axios.patch(url[, data[, config]])
axios.[请求方式](
[url],
{ [data] },
{ [config] }
).then((response) => {}).catch((err) => {});
🥈 配置默认值
// 设置默认配置
axios.defaults.method = "GET"; // 设置默认的请求类型为 GET
axios.defaults.baseURL = 'http://www.baidu.com'; // 设置基础请求 url
axios.defaults.timeout = 2000; // 设置默认请求的超时时间
axios({
url: '/user/00001'
}).then((response) => {}).catch((err) => {});
🥈 创建实例
// 可以使用自定义配置新建一个 axios 实例
// axios.create([config])
const instance = axios.create({
baseURL: 'https://www.baidu.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
instance.get(url[, config]);
// 有多个不同域名的时候就创建多个实例, 配置不同的参数
🥈 拦截器
在请求或响应被 then 或 catch 处理前拦截它们。
// 拦截器必须放在请求之前要不然不生效
// 添加请求拦截器
axios.interceptors.request.use(
function (config) {
// 在发送请求之前做些什么
console.log(config);
console.log("请求之前");
return config;
},
function (error) {
// 对请求错误做些什么
console.log("请求失败");
return Promise.reject(error);
}
);
// 添加响应拦截器
axios.interceptors.response.use(
function (response) {
// 对响应数据做点什么
console.log(response);
console.log("响应成功");
return response;
},
function (error) {
// 对响应错误做点什么
console.log("响应失败");
return Promise.reject(error);
}
);
// 创建的实例拦截器
const instance = axios.create({...});
// 添加实例请求拦截器
instance.interceptors.request.use(...);
// 添加实例响应拦截器
instance.interceptors.response.use(...);
// 移除拦截器
const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);
🥈 并发
axios.all(iterable)
axios.spread(callback)
axios.all(
[
axios.get("/test1"),
axios.get("/test2")
]
).then(
axios.spread((test1Res, test2Res) => {
console.log(test1Res, test2Res);
})
);
🥇 axios 源码分析
🥈 源码难点与流程分析
1. axios与Axios的关系
axios函数对应的是Axios.prototype.request方法通过bind(Axiox的实例)产生的函数
axios有Axios原型上的所有发特定类型请求的方法: get()/post()/put()/delete()
axios有Axios的实例上的所有属性: defaults/interceptors
后面又添加了create()/CancelToken()/all()
2. axios.create()返回的对象与axios的区别
1). 相同:
都是一个能发任意请求的函数: request(config)
都有发特定请求的各种方法: get()/post()/put()/delete()
都有默认配置和拦截器的属性: defaults/interceptors
2). 不同:
默认匹配的值不一样
instance没有axios后面添加的一引起方法: create()/CancelToken()/all()
3. axios发请求的流程
1). 整体流程: request(config) ===> dispatchRequest(config) ===> xhrAdapter(config)
2). request(config): 将请求拦截器 / dispatchRequest() / 响应拦截器 通过promise链串连起来, 返回promise
3). dispatchRequest(config): 转换请求数据 ===> 调用xhrAdapter()发请求 ===> 请求返回后转换响应数据. 返回promise
4). xhrAdapter(config): 创建XHR对象, 根据config进行相应设置, 发送特定请求, 并接收响应数据, 返回promise
4. axios的请求/响应拦截器是什么?
1). 请求拦截器: 在真正发请求前, 可以对请求进行检查或配置进行特定处理的函数,
包括成功/失败的函数, 传递的必须是config
2). 响应拦截器: 在请求返回后, 可以对响应数据进行特定处理的函数,
包括成功/失败的函数, 传递的默认是response
5. axios的请求/响应数据转换器是什么?
1). 请求转换器: 对请求头和请求体数据进行特定处理的函数
setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
return JSON.stringify(data)
2). 响应转换器: 将响应体json字符串解析为js对象或数组的函数
response.data = JSON.parse(response.data)
6. response的整体结构
{
data,
status,
statusText,
headers,
config,
request
}
7. error的整体结构
{
message,
request,
response
}
8. 如何取消未完成的请求
1).当配置了cancelToken对象时, 保存cancel函数
创建一个用于将来中断请求的cancelPromise
并定义了一个用于取消请求的cancel函数
将cancel函数传递出来
2.调用cancel()取消请求
执行cacel函数, 传入错误信息message
内部会让cancelPromise变为成功, 且成功的值为一个Cancel对象
在cancelPromise的成功回调中中断请求, 并让发请求的proimse失败, 失败的reason为Cacel对象
🥈 axios 源码分析 - 源码目录结构
├── /dist/ # 项目输出目录
├── /lib/ # 项目源码目录
│ ├── /adapters/ # 定义请求的适配器 xhr、http
│ │ ├── http.js # 实现http适配器(包装http包)
│ │ └── xhr.js # 实现xhr适配器(包装xhr对象)
│ ├── /cancel/ # 定义取消功能
│ ├── /core/ # 一些核心功能
│ │ ├── Axios.js # axios的核心主类
│ │ ├── dispatchRequest.js # 用来调用http请求适配器方法发送请求的函数
│ │ ├── InterceptorManager.js # 拦截器的管理器
│ │ └── settle.js # 根据http响应状态,改变Promise的状态
│ ├── /helpers/ # 一些辅助方法
│ ├── axios.js # 对外暴露接口
│ ├── defaults.js # axios的默认配置
│ └── utils.js # 公用工具
├── package.json # 项目信息
├── index.d.ts # 配置TypeScript的声明文件
└── index.js # 入口文件
🥈 axios 与 Axios 的关系
1.从语法上来说: axios 不是 Axios 的实例
2.从功能上来说: axios 是 Axios 的实例
3.axios 是 Axios.prototype.request 函数 bind() 返回的函数
4.axios 作为对象有 Axios 原型对象上的所有方法, 有 Axios 对象上所有属性
🥈 instance 与 axios 的区别
1.相同:
(1)都是一个能发任意请求的函数: request(config)
(2)都有发特定请求的各种方法: get()/post()/put()/delete()
(3)都有默认配置和拦截器的属性: defaults/interceptors
2.不同:
(1)默认匹配的值很可能不一样
(2)instance没有axios后面添加的一些方法: create()/CancelToken()/all()
🥈 axios 运行的整体流程
1.整体流程:
request(config) ==> dispatchRequest(config) ==> xhrAdapter(config)
2.request(config):
将请求拦截器 / dispatchRequest() / 响应拦截器 通过promise链串连起来, 返回promise
3.dispatchRequest(config):
转换请求数据 ===> 调用xhrAdapter()发请求 ===> 请求返回后转换响应数据. 返回promise
4.xhrAdapter(config):
创建XHR对象, 根据config进行相应设置, 发送特定请求, 并接收响应数据, 返回promise
🥈 axios 的请求/响应拦截器是什么
1.请求拦截器:
在真正发送请求前执行的回调函数
可以对请求进行检查或配置进行特定处理
成功的回调函数, 传递的默认是config(也必须是)
失败的回调函数, 传递的默认是error
2.响应拦截器
在请求得到响应后执行的回调函数
可以对响应数据进行特定处理
成功的回调函数, 传递的默认是response
失败的回调函数, 传递的默认是error
🥈 axios 的请求/响应数据转换器是什么
1.请求转换器: 对请求头和请求体数据进行特定处理的函数
if (utils.isObject(data)) {
setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
return JSON.stringify(data);
}
2.响应转换器: 将响应体json字符串解析为js对象或数组的函数
response.data = JSON.parse(response.data)
🥈 response 的整体结构
{
data,
status,
statusText,
headers,
config,
request
}
🥈 error 的整体结构
{
message,
response,
request,
}
🥈 如何取消未完成的请求
1.当配置了cancelToken对象时, 保存cancel函数
(1)创建一个用于将来中断请求的cancelPromise
(2)并定义了一个用于取消请求的cancel函数
(3)将cancel函数传递出来
2.调用cancel()取消请求
(1)执行cacel函数, 传入错误信息message
(2)内部会让cancelPromise变为成功, 且成功的值为一个Cancel对象
(3)在cancelPromise的成功回调中中断请求, 并让发请求的proimse失败, 失败的reason为Cacel对象
🥇 axios 二次封装
🥈 二次封装规则
1). 统一进行请求配置
2). 请求过程中 loading 提示
3). 请求体参数以 urlencoded 形式传递
urlencoded 格式,又叫 form 格式、x-www-form-urlencoded 格式
它是一种表单格式
组成格式
键值对组成
键和值之间用 = :name=poloyy
多个键值对之间用 & 隔开:name=poloyy&age=19
4). 请求成功的 value 不再是 response, 而是 response.data
5). 请求失败统一进行提示处理, 每个请求不需要单独处理
🥈 二次封装的常用设置
import axios from 'axios';
// 创建一个 axios 实例
const requests = axios.create({
baseURL: 'https://localhost:8000/api/', // 设置基础请求 url 地址
timeout: 1000, // 设置默认请求的超时时间
});
// 添加请求拦截器
requests.interceptors.request.use(
function (config) {
// 在发送请求之前做些什么
console.log("请求之前", config);
return config;
},
function (error) {
// 对请求错误做些什么
console.log("请求失败");
return Promise.reject(error);
}
);
// 添加响应拦截器
requests.interceptors.response.use(
function (response) {
// 对响应数据做点什么
console.log("响应成功", response);
return response.data;
},
function (error) {
// 对响应错误做点什么
console.log("响应失败");
return Promise.reject(error);
}
);
export default requests