axios相比浏览器提供的fetch,有更多的优点 :
npm i axios
axios(config)
import axios from 'axios';
axios({
// 请求方式
method: 'get',
// 请求地址
url: 'http:......'
}).then((res) => {
// 会返回一个promise,可以通过.then拿到结果
console.log('res', res.data);
});
axios.request(config)
import axios from 'axios';
axios.request({
// 请求方式
method: 'get',
// 请求地址
url: 'http:......'
}).then((res) => {
// 会返回一个promise,可以通过.then拿到结果
console.log('res', res.data);
});
axios.get(url[, config])
ps : 一样用法
axios.delete(url[, config])
axios.head(url[, config])
// 1. 可以在地址栏上直接跟上参数
axios.get('http://xxxxxx?id=123&name=coder').then((res) => {
console.log('res', res.data);
});
axios
.get('http://xxxxxx', {
// 2. 参数写在这里
params: {
id: 123,
name: 'coder'
}
})
.then((res) => {
console.log('res', res.data);
});
axios.post(url[, data[, config]])
ps : 一样用法
axios.put(url[, data[, config]])
axios.patch(url[, data[, config]])
import axios from 'axios';
axios
.post('http:xxxxxx', {
// 1. 把传递的参数直接写在这里
name: 'coder',
age: 18
})
.then((res) => {
console.log('res', res.data);
});
axios
.post('http:xxxxxx', {
// 2. 参数写在这里
data: {
name: 'star',
age: 16
}
})
.then((res) => {
console.log('res', res.data);
});
// 1.baseURL
const baseURL = "http://123.123.123.123:8000"
// 给axios实例配置公共的基础配置
axios.defaults.baseURL = baseURL
axios.defaults.timeout = 10000
axios.defaults.headers = {}
// 2.使用
axios.get("/abc/a").then(res => {
console.log("res:", res.data)
})
// 3. 如果地址完整,就不会使用默认的配置
axios.get("http://456.456.456.456:8000/abc/a").then(res => {
console.log("res:", res.data)
})
// 等待两个请求都完成后,才会调用then
axios.all([
axios.get("http://123.111.222.333:9001/a"),
axios.get("http://123.222.333.444:9001/b")
]).then(res => {
console.log("res:", res)
})
// 底层的本质是调用了promise.all
创建实例的目的 :
如果项目比较大,用的数据并不是来自同一个服务器
方式一 : 创建各个实例,配置不同的baseURL
方式二 : 配置proxy,根据相同路由名称来映射至不同的网络
// 创建实例一
const instance1 = axios.create({
baseURL: "http://123.123.123.123:9001",
timeout: 6000,
headers: {}
})
// 发送网络请求
instance1.get("/abc", {
params: {
id: 1
}
}).then(res => {
console.log("res:", res.data)
})
// 创建实例二
const instance2 = axios.create({
baseURL: "http://456.456.456.456:8000",
timeout: 10000,
headers: {}
})
/**
对实例配置拦截
这里使用默认实例
*/
axios.interceptors.request.use((config) => {
console.log("请求成功的拦截")
/**
可以做
开始loading的动画
对原来的配置进行一些修改
header
认证登录: token/cookie
请求参数进行某些转化
*/
config.header['token'] = '123321fasdfagea'
// 最后要把被指返回出去
return config
}, (err) => {
console.log("请求失败的拦截")
return err
})
axios.interceptors.response.use((res) => {
console.log("响应成功的拦截")
// 1.结束loading的动画
// 2.对数据进行转化, 再返回数据
return res.data
}, (err) => {
console.log("响应失败的拦截:", err)
return err
})
import axios from 'axios'
// 1. 创建一个类
class starRequest {
// 2. 构造函数中配置实例的基本配置
constructor(baseURL, timeout=10000) {
this.instance = axios.create({
baseURL,
timeout
})
}
// 3. 封装请求
request(config) {
return new Promise((resolve, reject) => {
this.instance.request(config).then(res => {
resolve(res.data)
}).catch(err => {
reject(err)
})
})
}
get(config) {
return this.request({ ...config, method: "get" })
}
post(config) {
return this.request({ ...config, method: "post" })
}
}
// 4. 导出
export default new starRequest("http://xxxxx:9001")
/**
* 配置文件
*/
export const BASE_URL = 'http://xxx:8000'
export const TIMEOUT = 10000
/**
* 封装axios请求
*/
// 1. 引入axios,导入类型
import axios from 'axios';
import type { AxiosInstance, AxiosRequestConfig } from 'axios';
class StarRequest {
// 实例类型 => AxiosInstance
private instance: AxiosInstance;
// config类型 => AxiosRequestConfig
constructor(config: AxiosRequestConfig) {
// 2. 创建实例
this.instance = axios.create(config);
}
// 3. 封装请求方法
request(config: AxiosRequestConfig) {
return this.instance.request(config);
}
get() {}
post() {}
}
export default StarRequest;
/**
* home模块: 用于存放home模块的接口
*/
import starRequest from '..';
export const getHomeData = () => {
return starRequest.request({
url: '/home/multidata'
});
};
/**
* 统一的出口文件,方便其他地方引入
*/
import { BASE_URL, TIMEOUT } from './config';
import StarRequest from './request';
// 导出实例
const starRequest = new StarRequest({
baseURL: BASE_URL,
timeout: TIMEOUT
});
export default starRequest;
// 导出请求方法
export * from './modules/home';
import { getHomeData } from './service';
getHomeData().then((res) => {
console.log(res.data);
});
全局拦截器 : 直接往instance上增加,每个请求都会触发
指定实例拦截器 : 给单独的实例再次增加拦截
ps : 拦截器可重复设置,不会覆盖
/**
* 配置文件
*/
// 普通接口
export const BASE_URL = 'http://xxx:1111'
// 需要拦截的接口
export const BASE_URL2 = 'http://yyyyyy:2222/api'
export const TIMEOUT = 10000
import { AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
// 类型扩展,继承axios的类型,添加自定义的拦截器
export interface StarRequestConfig extends AxiosRequestConfig {
// 设置自定义的拦截器,可选
interceptors?: {
requestSuccessFn?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig;
requestFailureFn?: (err: any) => any;
responseSuccessFn?: (res: AxiosResponse) => AxiosResponse;
responseFailureFn?: (err: any) => any;
};
}
/**
* 封装axios请求
*/
import axios from 'axios';
import type { AxiosInstance, AxiosRequestConfig } from 'axios';
// 1. 导入自定义扩展的类型,增加拦截器的可选参数
import type { StarRequestConfig } from './type';
class StarRequest {
private instance: AxiosInstance;
constructor(config: StarRequestConfig) {
this.instance = axios.create(config);
// 请求拦截器
this.instance.interceptors.request.use(
(config) => {
console.log('全局请求拦截器-请求成功');
// 添加token
config.headers.token = 'token666';
return config;
},
(err) => {
console.log('全局请求拦截器-请求失败');
return err;
}
);
// 响应拦截器
this.instance.interceptors.response.use(
(res) => {
console.log('全局响应拦截器-响应成功');
return res.data;
},
(err) => {
console.log('全局响应拦截器-响应失败');
return err;
}
);
// 2. 针对特定的实例,添加拦截器 => 使用?可选链
this.instance.interceptors.request.use(
config.interceptors?.requestSuccessFn,
config.interceptors?.requestFailureFn
);
this.instance.interceptors.response.use(
config.interceptors?.responseSuccessFn,
config.interceptors?.responseFailureFn
);
}
request(config: AxiosRequestConfig) {
return this.instance.request(config);
}
get() {}
post() {}
}
export default StarRequest;
import { starRequest2 } from '../index';
export const getEntiryList = () => {
return starRequest2.request({
url: '/entire/list',
params: {
offset: 0,
size: 20
}
});
};
/**
* 统一的出口文件,方便其他地方引入
*/
import { BASE_URL, BASE_URL2, TIMEOUT } from './config';
import StarRequest from './request';
// 导出请求方法
export * from './modules/home';
export * from './modules/entire';
// 导出实例 => 普通接口
const starRequest = new StarRequest({
baseURL: BASE_URL,
timeout: TIMEOUT
});
export default starRequest;
// 导出实例2 => 添加特定拦截的接口
export const starRequest2 = new StarRequest({
baseURL: BASE_URL2,
timeout: TIMEOUT,
interceptors: {
requestSuccessFn: (config) => {
console.log('实例2请求拦截 - 请求成功');
return config;
},
requestFailureFn: (err) => {
console.log('实例2请求拦截 - 请求失败');
return err;
},
responseSuccessFn: (res) => {
console.log('实例2响应拦截 - 响应成功');
return res;
},
responseFailureFn: (err) => {
console.log('实例2响应拦截 - 响应失败');
return err;
}
}
});
import { getHomeData, getEntiryList } from './service';
// 普通接口请求
getHomeData().then((res) => {
console.log(res);
});
// 特定拦截的接口请求
getEntiryList().then((res) => {
console.log(res);
});
/**
* home模块: 用于存放home模块的接口
*/
import starRequest from '..';
// 1. 定义接口
interface IHomeData {
data: any;
returnCode: string;
success: boolean;
}
export const getHomeData = () => {
// 2. 使用泛型, 指定返回值类型
return starRequest.request({
url: '/home/multidata'
});
};
import { starRequest2 } from '../index';
// 1. 定义接口
interface IEntireList {
list: any[];
errorCode: number;
totalCount: number;
}
export const getEntiryList = () => {
// 2. 使用泛型, 指定返回值类型
return starRequest2.request({
url: '/entire/list',
params: {
offset: 0,
size: 20
}
});
};
/**
* 重载request方法,增加泛型, 用于指定返回值类型
* 注意是传入第二个泛型R,而不是第一个泛型T
* 默认泛型T为any,如果不指定,返回值类型为unknown => 无法使用
*/
request(config: AxiosRequestConfig) {
return this.instance.request(config);
}
get(config: AxiosRequestConfig) {
return this.instance.request({ ...config, method: 'GET' });
}
post(config: AxiosRequestConfig) {
return this.instance.request({ ...config, method: 'POST' });
}
delete(config: AxiosRequestConfig) {
return this.instance.request({ ...config, method: 'DELETE' });
}
patch(config: AxiosRequestConfig) {
return this.instance.request({ ...config, method: 'PATCH' });
}