// PostMan 工具测试接口是不考虑跨域的
// npm i qs
// npm i blueimp-md5
/*
+ axios 基于 Promise 封装的 ajax 库 [核心还是基于 XMLHttpRequest 发送请求的]
+ 基于 axios 发送数据请求, 返回结果都是一个 Promise 实例
+ 默认情况下
+ 服务器返回的HTTP响应状态码是以 2 开始, 则让 Promise 状态为成功, 值是一个 response 对象
response = {
config: { ... }, // 发送axios请求设置的配置项
data: { ... }, // 服务器返回的响应主体信息
headers: { ... }, // 服务器返回的响应头信息
request: { ... }, // 原生的 xhr 对象
status: 200, // 服务器响应的HTTP状态码
statusText: 'OK', // 状态码描述
}
+ promise 状态为失败
@1 服务器有返回信息(response 对象存在) 只不过 HTTP 状态码不是以 2 开始的
reason = {
config: { ... }, // 发送axios请求设置的配置项
isAxiosError: true,
request: XMLHttpRequest实例对象,
response: 等同于成功获取的 response 对象
toJSON: function ...,
message: 'xxx',
...
}
@2 请求超时 或者 请求失败
reason = {
response: undefined,
code: "ECONNABORTED",
config: { ... }, // 发送axios请求设置的配置项
isAxiosError: true,
request: XMLHttpRequest实例对象,
toJSON: function ...,
message: 'xxx',
...
}
+ @3 断网了, 特点: 服务器没有任何返回信息
+ 我们可以自定义服务器返回的HTTP状态码为多少是成功, 为多少是失败!!
axios.get('url', {
...,
// axios的 ValidityStatus 配置项, 就是自定义promise实例状态是成功的条件
ValidityStatus: status => {
return status >= 200 && status < 300 // 默认处理机制
},
})
+ 基于 axios 发送请求的方式
+ @1 axios([config]) 或者 axios([url], [config])
+ @2 axios.request([config])
+ @3 axios.get/delete/head/options([url], [config])
+ @4 axios.post/put/patch([url], [data], [config]) => data 基于请求主体传递给服务器的信息
+ @5 let instance = axios.create([config])
创建的 instance 等同于 axios, 使用起来和axios一样 ...
instance.get([url], [config])
...
+ axios 发送请求时的配置项 config
+ url: 请求的地址 => 发送请求的时候, 但凡没有单独设置url 的, 都需要在配置项中指定
+ baseURL: 请求地址的通用前缀 => 最后发送请求的时候, 是把 baseURL 和 url拼接在一起发送的
axios.get('/user/list', {
baseURL: 'http://api.zhufeng.cn',
...
})
最后发送的请求地址是: 'http://api.zhufeng.cn/user/list'
特殊情况: 如果url地址本身已经存在了 http 或者 https 等信息, 说明url本身就已经是完整的地址了,
baseURL 的值则无需再拼接了
+ transformRequest: (data, headers) => {
// data => 自己传递的 data
// headers: 设置的请求头信息{对象}
return xxxx; 返回值是啥, 最后基于请求主体传递的就是啥
}
它只针对于POST请求, 把我们自己传递的data 格式化为指定的格式, 然后再基于请求主体发送给服务器
axios内部做了一个处理, 根据我们最后处理好的 data 的格式, 自动设置请求头中的Content-Type值(不一定完全准确).
@1 客户端基于请求主体传递给服务器的数据格式
+ form-data Content-Type: 'multipart/form-data';
主要应用于文件上传/表单提交
+ urlencoded Content-Type: 'application/x-www-form-urlencoded';
GET系列请求: 是基于URL问号传参把信息传递给服务器的 ?xxx=xxx&xxx=xxx
xxx=xxx&xxx=xxx 这种字符串就是urlencoded格式字符串
+ raw 泛指, 代指文本格式(普通格式文本字符串; json格式字符串; ...)
+ 普通格式文本字符串 Content-Type: 'text/plain'
+ JSON 格式字符串: Content-Type: 'application/json'
...
+ binary 进制格式数据 主要应用于文件上传
+ @2 axios 内部在默认情况下, 如果我们 data 传递的是个普通对象, 而且也没有经过 transformRequest 处理,
则内部默认会把对象变为JSON格式字符串传递给服务器
+ transformResponse: function (data, headers) {
// 对发送的 data 进行任意转换处理
// data: 从服务器拿到的结果, 而且是响应主体信息(服务器响应的主体信息一般都是 JSON 格式字符串)
return data;
},
在我们自己的 .then/catch之前, 对服务器返回的结果进行修改
+ headers: { ... } 自定义请求头信息
+ params: {...} GET系列请求, 基于 URL 问号参数, 把信息传递给服务器; 我们params一般设置为对象,
axios 内部会把对象变为 urlencoded 格式拼接到URL的末尾
paramsSerializer: function (params) {
// 默认也是通过 qs.stringify() 对 params 进行处理的
return Qs.stringify(params, {arrayFormat: 'brackets'})
},
+ data: { ... } // POST 系列请求, 基于请求主体传递的信息
+ timeout: 12 // 设置超时时间, 写0就是不设置, 单位毫秒
+ withCredentials: false, // 在CORS跨域请求中, 是否允许携带资源凭证
+ responseType: 'json', // responseType 表示浏览器将要响应的数据类型;
选项包括: 'arraybuffer', 'document', 'json'(默认值), 'text', 'stream'
+ onUploadProgress: function (progressEvent) { // onUploadProgress 监听上传的进度
// 处理原生进度事件
},
+ onDownloadProgress: function (progressEvent) { // onDownloadProgress 监听下载的进度
// 处理原生进度事件
},
+ validateStatus: function (status) {
return status >= 200 && status < 300; // 默认值
},
// 定义服务器但会的状态码是多少, promise 实例是成功的
+ axios 请求的取消, 依赖于 axios.CancelToken 完成
....
+ 请求拦截器
+ 请求拦截器: 当 axios 把各方面配置都处理好了, 在即将基于这些配置项服务器发送请求的时候, 触发请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
// config 存储的是axios处理好的配置, 我们一般在请求拦截器中修改配置
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
+ 响应拦截器
+ 响应拦截器: 服务器返回结果, axios 已经知道返回的promise实例状态是成功还是失败了, 在自己调用 then/catch
之前, 先根据promise状态, 把响应拦截器中设置的方法执行
axios.interceptors.response.use(response => {
// 2xx 范围内的状态码都会触发该函数。
// promise实例是成功的, 执行这个方法: response 存储服务器返回的结果
return response;
}, reason => {
// 超出 2xx 范围的状态码都会触发该函数。
// promise实例是失败的, 执行这个方法: reason 存储失败的原因
return Promise.reject(reason);
});
响应拦截器中的方法, 相当于自己axios.get('url', params: {...}).then(response => {}).catch(reason => {})之前
先 .then(onfulfilled, onrejected) 了
*/
// let xhr = new XMLHttpRequest();
// xhr.open('GET', './1.json');
// xhr.setRequestHeader('Content-Type', 'multipart/form-data');
// xhr.onreadystatechange = function () {
// if (xhr.readyState === 4 && xhr.status === 200) {
// console.log(xhr.responseText);
// }
// }
// xhr.send(null);
// async function getDepartmentList () {
// try {
// const res = await axios.get('/user/list2', {
// ValidityStatus: status => {
// return status >= 200 && status < 300 // 以2开头的认为是成功
// // return status >= 200 && status < 400 // 以 2 和 3 开头的认为是成功
// },
// timeout: 1,
// params: {
// departmentId: 12,
// search: ''
// }
// })
// console.log(res)
// } catch (error) {
// console.dir(error);
// }
// }
import qs from 'qs'
import md5 from 'blueimp-md5'
const source = axios.CancelToken.source();
async function addDepartment () {
axios.post(
'/user/login',
{
account: '13213188866',
password: md5('admin123456')
},
{
transformRequest: (data) => {
// 如果 data 是纯粹对象才可以调用 qs.stringify() 进行转换
if (Object.prototype.toString.call(data) === '[object Object]') {
return qs.stringify(data) // 把对象变为 urlencoded 格式字符串
}
return data
},
transformResponse: function (data) { // 返回的data 一般是json格式字符串
console.log(data)
return JSON.parse(data)
},
CancelToken: source.token
}
).then(response => {
console.log(response)
}).catch(reason => {
console.log(reason)
console.log(reason.message) // 取消原因 => '我把请求取消了~~'
})
setTimeout(function () {
source.cancel('我把请求取消了~~')
})
}
// import axios from 'axios'
// console.dir(axios);
// const source = axios.CancelToken.source()
// // 请求接口测试
// axios.get('/api/news_latest', {
// validateStatus: status => (status >= 200 && status > 300),
// timeout: 60000,
// cancelToken: source.token
// }).then(response => {
// console.log('response', response)
// return {
// data: response.data,
// status: response.status
// }
// }).then(res => {
// console.log('res', res) // 想要的主体信息
// }).catch(reason => {
// console.dir(reason)
// /* @1 服务器有反馈信息, 但是HTTP状态码不是以2开始的 reason.response.status
// reason = {
// code: "ERR_BAD_REQUEST",
// config: { transitional: {… }, transformRequest: Array(1), transformResponse: Array(1), timeout: 0, adapter: ƒ, … },
// message: "Request failed with status code 404",
// name: "AxiosError",
// request: XMLHttpRequest { onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, … },
// response: { data: '', status: 404, statusText: 'Not Found', headers: {… }, config: {… }, … }
// }
// @2 请求超时 reason.code == "ECONNABORTED" reason.response = undefined
// @3 请求中断 reason是Cancle的实例对象, reason.message存储中断的原因, 可以基于 axios.isCancel(reason)检测是否为手动中断请求的
// */
// console.log(axios.isCancel(reason))
// })
// // 取消发送请求
// source.cancel()
/**
* axios的二次封装, 就是根据项目需要 后台要求, 把一些 axios 发送请求, 公共的部分进行提取
* 这样再次基于axios发送请求, 就可以简化一些了
* 项目中有 100 个接口, 其中 30 个是调用 A服务器; 40个接口调用B服务器; 30个调用C服务器
* 部分接口和封装的还不太一样
*/
```
axios详细解读
于 2024-05-17 07:44:07 首次发布