🥇 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. 请求行: 请求方式/url2. 多个请求头: 一个请求头由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.passwordparams 参数:路由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/DELETE2. 非 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 是用于请求的服务器 URLurl: '/user',// method 是创建请求时使用的方法method: 'get',/*** 如果没有配置 method 默认就是 get* method 常见的可选值为 get / post / put / delete*/// baseURL 将自动加在 url 前面,除非 url 是一个绝对 URL// 比如这里的请求地址就是: https://www.baidu.com/api/user// 它可以通过设置一个 baseURL 便于为 axios 实例的方法传递相对 URLbaseURL: 'https://www.baidu.com/api/',// transformRequest 允许在向服务器发送前,修改请求数据// 只能用在 PUT, POST 和 PATCH 这几个请求方法// 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 StreamtransformRequest: [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 专属: Streamdata: {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 将被 rejectevalidateStatus: 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 tokencancelToken: new CancelToken(function (cancel) {})}
🥈 请求
// 通用请求axios({method: "GET", // 请求方式url: "http://localhost:3000/student", // URLparams: { // 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"; // 设置默认的请求类型为 GETaxios.defaults.baseURL = 'http://www.baidu.com'; // 设置基础请求 urlaxios.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/interceptors2). 不同:默认匹配的值不一样instance没有axios后面添加的一引起方法: create()/CancelToken()/all()3. axios发请求的流程1). 整体流程: request(config) ===> dispatchRequest(config) ===> xhrAdapter(config)2). request(config): 将请求拦截器 / dispatchRequest() / 响应拦截器 通过promise链串连起来, 返回promise3). dispatchRequest(config): 转换请求数据 ===> 调用xhrAdapter()发请求 ===> 请求返回后转换响应数据. 返回promise4). xhrAdapter(config): 创建XHR对象, 根据config进行相应设置, 发送特定请求, 并接收响应数据, 返回promise4. axios的请求/响应拦截器是什么?1). 请求拦截器: 在真正发请求前, 可以对请求进行检查或配置进行特定处理的函数,包括成功/失败的函数, 传递的必须是config2). 响应拦截器: 在请求返回后, 可以对响应数据进行特定处理的函数,包括成功/失败的函数, 传递的默认是response5. 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/interceptors2.不同:(1)默认匹配的值很可能不一样(2)instance没有axios后面添加的一些方法: create()/CancelToken()/all()
🥈 axios 运行的整体流程

1.整体流程:request(config) ==> dispatchRequest(config) ==> xhrAdapter(config)2.request(config):将请求拦截器 / dispatchRequest() / 响应拦截器 通过promise链串连起来, 返回promise3.dispatchRequest(config):转换请求数据 ===> 调用xhrAdapter()发请求 ===> 请求返回后转换响应数据. 返回promise4.xhrAdapter(config):创建XHR对象, 根据config进行相应设置, 发送特定请求, 并接收响应数据, 返回promise
🥈 axios 的请求/响应拦截器是什么

1.请求拦截器:在真正发送请求前执行的回调函数可以对请求进行检查或配置进行特定处理成功的回调函数, 传递的默认是config(也必须是)失败的回调函数, 传递的默认是error2.响应拦截器在请求得到响应后执行的回调函数可以对响应数据进行特定处理成功的回调函数, 传递的默认是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=194). 请求成功的 value 不再是 response, 而是 response.data5). 请求失败统一进行提示处理, 每个请求不需要单独处理
🥈 二次封装的常用设置
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
