index.ts 用来暴露实例
import EnclosureHttp from "@/utils/http/requset";
const http = new EnclosureHttp();
export default http;
request.ts 实现 axios 创建实例 请求拦截 响应拦截 和默认 的get post 封装(偷懒了,没有封装自定义的 get post put delete )
import Axios, {
AxiosRequestConfig,
AxiosResponse,
AxiosError,
AxiosInstance,
} from "axios";
import { Request } from "@/utils/http/types";
import { ElMessage } from "element-plus";
/**
* 封装的 element-plus 的消息提示框
* @param msg
* @param type
*/
const message = (msg: string, type?: string) => {
ElMessage({
message: msg,
type: type || "warning",
duration: 1500,
});
};
/**
* 默认 create Axios 的配置参数
*/
const defaultConfig: AxiosRequestConfig = {
baseURL: "",
timeout: 10000, //10秒超时
withCredentials: true,
responseType: "json",
transformRequest: [
(data) => {
//对请求的参数进行处理
data = JSON.stringify(data);
return data;
},
],
validateStatus() {
// 使用async-await,处理reject情况较为繁琐,所以全部返回resolve,在业务代码中处理异常
return true;
},
transformResponse: [
(data) => {
//对响应的数据进行处理
if (typeof data === "string" && data.startsWith("{")) {
data = JSON.parse(data);
}
return data;
},
],
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest",
},
};
/**
* Axios create的时候后去的配置参数
* @param config
*/
const getConfig = (config?: AxiosRequestConfig): AxiosRequestConfig => {
if (!config) return defaultConfig;
return defaultConfig;
};
/**
* 自定义封装的Axios 类
*/
class EnclosureHttp {
constructor() {
this.httpInterceptorsRequest();
this.httpInterceptorsResponse();
}
/**
* Axios 实例
* @private
*/
private static axiosInstance: AxiosInstance = Axios.create(getConfig());
/**
* 请求拦截
* @private
*/
private httpInterceptorsRequest(): void {
EnclosureHttp.axiosInstance.interceptors.request.use(
(config: AxiosRequestConfig) => {
/*
* 在请求发出去之前作出一下处理
* */
// console.log("config=>:", config);
return config;
},
(err) => {
return Promise.resolve(err);
}
);
}
/**
* 响应拦截
* @private
*/
private httpInterceptorsResponse(): void {
EnclosureHttp.axiosInstance.interceptors.response.use(
(response: AxiosResponse) => {
/*
* 对响应的数据作出一些处理
* */
const { status } = response;
let msg = "";
if (status < 200 || status >= 300) {
// 处理http错误,抛到业务代码
if (typeof response.data === "string") {
msg = "打盹了!!!";
response.data = { msg };
} else {
response.data.msg = msg;
}
}
return response;
},
(error: AxiosError) => {
//请求出错的验证
const { response } = error;
if (response) {
// 请求已发出,但是不在2xx的范围
this.errorHandle(response.status, response.data.message);
return Promise.reject(response);
} else {
// 处理断网的情况
// eg:请求超时或断网时,更新state的network状态
// network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
// 后续增加断网情况下做的一些操作
return Promise.reject(error);
}
}
);
}
/**
* 请求失败后的错误统一处理
* @param status 请求失败的状态码
* @param other
*/
private errorHandle = (status: number, other: string) => {
// 状态码判断
switch (status) {
case -1: // -1: 未登录状态,跳转登录页
message("未登录状态");
break;
case 403: // 403 token过期
message("登录过期,请重新登录");
break;
case 404: // 404请求不存在
message("请求错误!!!");
break;
default:
message(other);
}
};
/**
* get方法
* @param url 路径
* @param params 参数
* @param config
*/
public reqGet: Request = async (
url: string,
params?: unknown,
config?: AxiosRequestConfig
) => {
return await EnclosureHttp.axiosInstance.get(url, { params, ...config });
};
/**
* post 方法
* @param url 路径
* @param params 参数
* @param config
*/
public reqPost: Request = (
url: string,
params: unknown = {},
config?: AxiosRequestConfig
) => {
return EnclosureHttp.axiosInstance.post(url, { data: params }, config);
};
/**
* Axios init GET方法
* @param url 路径
* @param params 参数
* @param config
*/
public get: Request = (
url: string,
params?: unknown,
config?: AxiosRequestConfig
) => {
return Axios.get(url, { params, ...config });
};
/**
* Axios init POST 方法
* @param url 路径
* @param params 参数
* @param config
*/
public post: Request = (
url: string,
params: unknown = {},
config?: AxiosRequestConfig
) => {
return Axios.post(url, { data: params }, config);
};
}
export default EnclosureHttp;
type.ts 是类型和接口文件
import { AxiosRequestConfig } from "axios";
export interface IUser {
name: string;
pasword: string;
}
// 定制业务相关的网络请求响应格式, T 是具体的接口返回类型数据
export interface CustomSuccessData<T> {
status: number;
statusText: string;
message?: string;
data: T;
[keys: string]: unknown;
}
/**
*
*/
export interface Request {
<T>(
url: string,
params?: Record<string, unknown>,
config?: AxiosRequestConfig
): Promise<CustomSuccessData<T>>;
}
最后实际使用:拿网易云API 举例
cloudMusic.ts
import http from "@/utils/http";
import { Klyric, Rows, Songs } from "@/api/cloudMusic/types.ts";
const cloudBaseUrl = "https://autumnfish.cn/";
// const cloud = "/api";
/**
* 网易云音乐开放接口的数据
*/
export class CloudApi {
/*
* 搜索音乐
* @Params: {keywords} : 关键字
* */
static async searchMusic(params: { keywords: string }): Promise<Rows<Songs>> {
const res = await http.reqGet<Rows<Songs>>(
cloudBaseUrl + `/search`,
params
);
return res.data;
}
/*
* 获取音乐详情
* @Params: {ids} : 音乐ID
* */
static async searchMusicDetail(params: { ids: number }) {
return await http.reqGet(cloudBaseUrl + `/song/detail`, params);
}
/*
* 获取歌词
* @Params: {id} : 音乐ID
* */
static async getMusicLyric(params: { id: number }): Promise<Klyric> {
const res = await http.reqGet<Klyric>(cloudBaseUrl + `/lyric`, params);
return res.data;
}
/*
* 获取音乐 -- 暂不可用
* @Params: {id} : 音乐的ID
* */
static async getMusicUrl(params: { id: number }): Promise<unknown> {
const res = await http.reqGet(cloudBaseUrl + `/song/url`, params);
return res.data;
}
}
types.ts 类型和接口
//搜索音乐 接口返回的数据类型
export interface Rows<T> {
result?: Result<T>;
code: number;
}
/**
*搜索音乐返回的数据类型
*/
type Result<T> = {
hasMore: boolean;
songCount: number;
songs: Array<T>;
};
/*
* 获取的音乐列表
* */
export interface Songs {
album: album;
alias: Array<string>;
artists: Array<artist>;
copyrightId: number;
duration: number;
fee: number;
ftype: number;
id: number;
mark: number;
mvid: number;
name: string;
rUrl: unknown;
rtype: number;
status: number;
}
/*
* //
* */
type album = {
artist: Array<artist>;
copyrightId: number;
id: number;
mark: number;
name: string;
picId: number;
publishTime: number;
size: number;
status: number;
};
/*
* //
* */
type artist = {
albumSize: number;
alias: Array<unknown>;
id: number;
img1v1: number;
img1v1Url: string;
name: string;
picId: number;
picUrl: string;
trans: string | number;
};
export interface Klyric {
code: number;
klyric: Lrc;
lrc: Lrc;
qfy: boolean;
sfy: boolean;
sgc: boolean;
tlyric: Lrc;
}
export interface Lrc {
lyric: string;
version: number;
}