axios 基础
ajax、fetch、xhr 区别
Ajax 是一个技术统称,是一个概念模型,它囊括了很多技术,并不特指某一技术,它很重要的特性之一就是让页面实现局部刷新。
Ajax 是一种思想,XMLHttpRequest 只是实现 Ajax 的一种方式。xhr 的请求方式,如果请求中套请求容易造成回调地狱。
function ajax(url) {
const xhr = new XMLHttpRequest();
xhr.open("get", url, false);
xhr.onreadystatechange = function () {
// 异步回调函数
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.info("响应结果", xhr.response)
}
}
}
xhr.send(null);
}
ajax('https://smallpig.site/api/category/getCategory')
Fetch 是在 ES6 出现的,它使用了 ES6 提出的 promise 对象。它是 XMLHttpRequest 的替代品。
它有如下特点:
- 使用 promise,不使用回调函数。
- 采用模块化设计,比如 rep、res 等对象分散开来,比较友好。
- 通过数据流对象处理数据,可以提高网站性能。
function ajaxFetch(url) {
fetch(url).then(res => res.json()).then(data => {
console.info(data)
})
}
ajaxFetch('https://smallpig.site/api/category/getCategory')
axios 是什么
Axios 是一个基于 Promise 的 HTTP 库。它封装了 xhr 和 http 模块,分别在浏览器和 node.js 环境下实现了 ajax,发送异步请求。
基本使用
安装
npm i axios
请求方式
axios 的主要 api 就是axios(config)
函数,接收配置对象发送请求。
config 最常见的三个参数就是
- method:请求类型
- url:请求路径
- data:提交的数据
axios 也可以直接接收 url,再跟上 config 对象,config 配置对象是可选的,如果没有传入,则是默认发送 get 请求。axios(url[,config])
import axios from 'axios'
// 发送 POST 请求
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
// 发送 GET 请求(默认的方法)
axios('/user/12345');
请求类型封装
我们导入的 axios 其实是个实例对象,虽然它能直接当函数使用。为了方便使用,axios 实例对象中封装了相应请求类型的方法:
axios.request(config)
request 方法和 axios( ) 使用是没有区别的
但是下面的方法,axios 进一步封装了,config 配置对象中可以省略 url,method,data 选项:
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.all(iterable)
axios.spread(callback)
axios.all 实际就是 promise.all ,它能发送多个请求,并且等待所有请求结束才会调用 then 或 catch 方法。全部成功才调用 then,有失败就调用 catch。
axios
// 多个请求放在数组中
.all([axios.get("http://localhost/get"), axios.post("http://localhost/post")])
// 返回结果也是在数组中
.then((res) => {
console.log(res[0].data);
console.log(res[1].data);
})
.catch((err) => {
console.log("failure");
});
res 的类型
我们知道 axios 返回的是一个 promise 对象,其实在 ts 中,promise 对象是有类型的。res 的类型和 promise 的类型是一样的。
new Promise<string>(resolve => { // 假设 promise 类型为 string
resolve('hhh') // resolve 接收的类型则必须为 string
}).then(res => { // 而 res 来自 resolve 的参数,所以 res 类型也会是 string
console.log(res) // hhh
})
响应内容的结构
axios 发送请求后,会对请求结果封装成一定结构后返回。也就是 res 的内容是什么?
{
// `data` 由服务器提供的响应数据
data: {},
// `status` 来自服务器响应的 HTTP 状态码
status: 200,
// `statusText` 来自服务器响应的 HTTP 状态信息
statusText: 'OK',
// `headers` 服务器响应的头
headers: {},
// `config` 为该次请求的配置信息
config: {},
// 'request'
// `request` is the request that generated this response
// It is the last ClientRequest instance in node.js (in redirects)
// and an XMLHttpRequest instance the browser
// request 就是发起请求的实例对象,浏览器中就是 xhr 对象
request: {}
}
配置对象常用的配置项
{
// 路径url
url: '/user',
// 请求方法,默认get
method: 'get',
//基础url,最终请求的url是 baseURL+url拼接,所以再全局设置默认,可以使得发送请求时的url变得简洁
baseURL: 'https://some-domain.com/api/',
//设置请求头
headers: {'X-Requested-With': 'XMLHttpRequest'},
//设置请求url的query参数,可以使得url简洁。
//比如url是https://some-domain.com/api/user 然后params如下设置,那么最终的url是:
//https://some-domain.com/api/user?ID=12345&name=Jack
params: {
ID: 12345,
name:"Jack"
},
//设置请求体
data: {
firstName: 'Fred'
},
//设置请求的另外一种格式,不过这个是直接设置字符串的
data: 'Country=Brasil&City=Belo Horizonte',
//请求超时,单位毫秒,默认0,不超时。
timeout: 1000,
//响应数据类型,默认json
responseType: 'json',
//响应数据的编码规则,默认utf-8
responseEncoding: 'utf8',
//响应体的最大长度
maxContentLength: 2000,
// 请求体的最大长度
maxBodyLength: 2000,
//设置响应状态码为多少时是成功,调用resolve,否则调用reject失败
//默认是大于等于200,小于300
validateStatus: function (status) {
return status >= 200 && status < 300;
},
默认请求配置
我们可以设置全局的默认配置,这样可以避免在不同请求中写一些重复配置,比如 baseURL、timeout 等。
// 全局默认配置
axios.default.baseURL = "http://ahcheng.top"
axios.default.timeout = 100000
// 请求 http://ahcheng.top/user
axios.get('/user', { // 因为全局配置了,所以可以省略 url 前面部分
timeout: 20000 // 给请求单独设置超时时间
})
axios 实例
导入 axios 模块,默认提供了一个 axios 实例。我们还可以通过axios.create([config])
方法创建一个全新的 axios 实例对象,新的实例对象自然拥有所有封装好的请求方法。
并且创建实例时可以进行一些初始化配置。比如设置 baseURL 等。
一般情况下一个 axios 实例够用了,但是如果后台存在多个服务器,一个全局默认配置可能就不方便了。则可以针对不同服务器新建一个 axios 实例,并设置对应的 baseURL 等一些默认配置。
// Set config defaults when creating the instance
const instance = axios.create({
baseURL: 'https://api.example.com'
});
// Alter defaults after instance has been created
instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
拦截器
分为两种,请求拦截和响应拦截。底层通过 promise 实现。
use 方法接收两个处理函数,第一个是拦截成功的处理函数,第二个是错误处理函数。
axios.interceptors.request.use(config => return config, err => {})
对于请求拦截,第一个函数可以接收本次请求的 config 配置对象,并且需要返回该 config 对象。错误处理函数,可以接收 error 对象,返回类型可以为空。
axios.interceptors.response.use(res => {}, err => {})
对于响应拦截,第一个函数能接收到请求的响应内容 response,并且返回值也能为空。错误处理函数和请求拦截一致。
根据这种拦截函数的设计,请求拦截中就很方便对配置对象进行一些更定制化的修改,响应拦截中则很适合对响应数据进行一些预处理。
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么,传入了 config 对象,所以比如可以进行一些配置
return config.timeout = 1000;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么,传入了 res,所以可以过滤掉 res 中其他结构,让 then 直接拿到请求结果
return response.data;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
axios.get(url).then(res => console.log(res)) // 直接打印出请求数据
如果你想在稍后移除拦截器,可以这样:
const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);
可以为自定义 axios 实例添加拦截器
const instance = axios.create();
instance.interceptors.request.use(function () {/*...*/});
取消请求
使用 cancel token 可以主动取消请求。获取到取消令牌,就可以到处使用,取消多个请求。
可以使用 CancelToken.source 工厂方法创建 cancel token,还可以通过传递一个 executor 参数函数到 CancelToken 的构造函数来创建 cancel token。
我们一般使用第二种方式获取到 cancel token
const CancelToken = axios.CancelToken;
let cancel;
axios.get('/user/12345', {
// 在配置中配置 cancelToken 选项
cancelToken: new CancelToken(function executor(c) {
// executor 函数接收一个 cancel 函数作为参数
cancel = c; // 将取消函数赋值出去,供全局使用
})
});
// cancel the request
cancel();