This commit is contained in:
Your Name
2026-03-01 14:17:59 +08:00
parent 65aa12f146
commit a07e844c47
6071 changed files with 777651 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
import { RequestTask } from './type'
const cancelerMap = new Map<string, RequestTask>()
export class RequestCancel {
private static instance?: RequestCancel
static createInstance() {
return this.instance ?? (this.instance = new RequestCancel())
}
add(url: string, requestTask: RequestTask) {
this.remove(url)
if (cancelerMap.has(url)) {
cancelerMap.delete(url)
}
cancelerMap.set(url, requestTask)
}
remove(url: string) {
if (cancelerMap.has(url)) {
const requestTask = cancelerMap.get(url)
requestTask && requestTask.abort()
cancelerMap.delete(url)
}
}
}
const requestCancel = RequestCancel.createInstance()
export default requestCancel
+140
View File
@@ -0,0 +1,140 @@
import { merge } from 'lodash-es'
import { isFunction } from '@vue/shared'
import { HttpRequestOptions, RequestConfig, RequestOptions, UploadFileOption } from './type'
import { RequestErrMsgEnum, RequestMethodsEnum } from '@/enums/requestEnums'
import requestCancel from './cancel'
export default class HttpRequest {
private readonly options: HttpRequestOptions
constructor(options: HttpRequestOptions) {
this.options = options
}
/**
* @description 重新请求
*/
retryRequest(options: RequestOptions, config: RequestConfig) {
const { retryCount, retryTimeout } = config
if (!retryCount || options.method?.toUpperCase() == RequestMethodsEnum.POST) {
return Promise.reject()
}
uni.showLoading({ title: '加载中...' })
config.hasRetryCount = config.hasRetryCount ?? 0
if (config.hasRetryCount >= retryCount) {
return Promise.reject()
}
config.hasRetryCount++
config.requestHooks.requestInterceptorsHook = (options) => options
return new Promise((resolve) => setTimeout(resolve, retryTimeout))
.then(() => this.request(options, config))
.finally(() => uni.hideLoading())
}
/**
* @description get请求
*/
get<T = any>(options: RequestOptions, config?: Partial<RequestConfig>): Promise<T> {
return this.request({ ...options, method: RequestMethodsEnum.GET }, config)
}
/**
* @description post请求
*/
post<T = any>(options: RequestOptions, config?: Partial<RequestConfig>): Promise<T> {
return this.request({ ...options, method: RequestMethodsEnum.POST }, config)
}
/**
* @description 上传图片
*/
uploadFile(options: UploadFileOption, config?: Partial<RequestConfig>) {
let mergeOptions: RequestOptions = merge({}, this.options.requestOptions, options)
const mergeConfig: RequestConfig = merge({}, this.options, config)
const { requestInterceptorsHook, responseInterceptorsHook, responseInterceptorsCatchHook } =
mergeConfig.requestHooks || {}
if (requestInterceptorsHook && isFunction(requestInterceptorsHook)) {
mergeOptions = requestInterceptorsHook(mergeOptions, mergeConfig)
}
return new Promise((resolve, reject) => {
uni.uploadFile({
...mergeOptions,
success: async (response) => {
if (response.statusCode == 200) {
response.data = JSON.parse(response.data)
if (responseInterceptorsHook && isFunction(responseInterceptorsHook)) {
try {
response = await responseInterceptorsHook(response, mergeConfig)
resolve(response)
} catch (error) {
reject(error)
}
return
}
resolve(response)
}
},
fail: async (err) => {
if (
responseInterceptorsCatchHook &&
isFunction(responseInterceptorsCatchHook)
) {
reject(await responseInterceptorsCatchHook(mergeOptions, err))
return
}
reject(err)
}
})
})
}
/**
* @description 请求函数
*/
async request(options: RequestOptions, config?: Partial<RequestConfig>): Promise<any> {
let mergeOptions: RequestOptions = merge({}, this.options.requestOptions, options)
const mergeConfig: RequestConfig = merge({}, this.options, config)
const { requestInterceptorsHook, responseInterceptorsHook, responseInterceptorsCatchHook } =
mergeConfig.requestHooks || {}
if (requestInterceptorsHook && isFunction(requestInterceptorsHook)) {
mergeOptions = requestInterceptorsHook(mergeOptions, mergeConfig)
}
return new Promise((resolve, reject) => {
const requestTask = uni.request({
...mergeOptions,
async success(response) {
if (responseInterceptorsHook && isFunction(responseInterceptorsHook)) {
try {
response = await responseInterceptorsHook(response, mergeConfig)
resolve(response)
} catch (error) {
reject(error)
}
return
}
resolve(response)
},
fail: async (err) => {
if (err.errMsg == RequestErrMsgEnum.TIMEOUT) {
this.retryRequest(mergeOptions, mergeConfig)
.then((res) => resolve(res))
.catch((err) => reject(err))
return
}
if (
responseInterceptorsCatchHook &&
isFunction(responseInterceptorsCatchHook)
) {
reject(await responseInterceptorsCatchHook(mergeOptions, err))
return
}
reject(err)
},
complete(err) {
if (err.errMsg !== RequestErrMsgEnum.ABORT) {
requestCancel.remove(options.url)
}
}
})
const { ignoreCancel } = mergeConfig
!ignoreCancel && requestCancel.add(options.url, requestTask)
})
}
}
+99
View File
@@ -0,0 +1,99 @@
import HttpRequest from "./http";
import { merge } from "lodash-es";
import { HttpRequestOptions, RequestHooks } from "./type";
import { getToken } from "../auth";
import { RequestCodeEnum, RequestMethodsEnum } from "@/enums/requestEnums";
import { useUserStore } from "@/stores/user";
import appConfig from "@/config";
import { getClient } from "../client";
const requestHooks: RequestHooks = {
requestInterceptorsHook(options, config) {
const { urlPrefix, baseUrl, withToken, isAuth } = config;
options.header = options.header ?? {};
if (urlPrefix) {
options.url = `${urlPrefix}${options.url}`;
}
if (baseUrl) {
options.url = `${baseUrl}${options.url}`;
}
const token = getToken();
// 添加token
if (withToken && !options.header.token) {
options.header.token = token;
}
options.header.version = appConfig.version;
// options.header.terminal = getClient();
return options;
},
async responseInterceptorsHook(response, config) {
const { isTransformResponse, isReturnDefaultResponse, isAuth } = config;
//返回默认响应,当需要获取响应头及其他数据时可使用
if (isReturnDefaultResponse) {
return response;
}
// 是否需要对数据进行处理
if (!isTransformResponse) {
return response.data;
}
const { logout } = useUserStore();
const { code, data, msg, show } = response.data as any;
switch (code) {
case RequestCodeEnum.SUCCESS:
msg && show && uni.$u.toast(msg);
return data;
case RequestCodeEnum.FAILED:
uni.$u.toast(msg);
return Promise.reject(msg);
case RequestCodeEnum.TOKEN_INVALID:
logout();
if (isAuth && !getToken()) {
uni.navigateTo({
url: "/pages/login/login",
});
}
return Promise.reject(msg);
default:
return data;
}
},
async responseInterceptorsCatchHook(options, error) {
if (options.method?.toUpperCase() == RequestMethodsEnum.POST) {
uni.$u.toast("请求失败,请重试");
}
return Promise.reject(error);
},
};
const defaultOptions: HttpRequestOptions = {
requestOptions: {
timeout: appConfig.timeout,
},
baseUrl: appConfig.baseUrl,
//是否返回默认的响应
isReturnDefaultResponse: false,
// 需要对返回数据进行处理
isTransformResponse: true,
// 接口拼接地址
urlPrefix: "api",
// 忽略重复请求
ignoreCancel: false,
// 是否携带token
withToken: true,
isAuth: false,
retryCount: 2,
retryTimeout: 1000,
requestHooks: requestHooks,
};
function createRequest(opt?: HttpRequestOptions) {
return new HttpRequest(
// 深度合并
merge(defaultOptions, opt || {})
);
}
const request = createRequest();
export default request;
+30
View File
@@ -0,0 +1,30 @@
export type RequestOptions = UniApp.RequestOptions
export type ResponseResult =
| UniApp.RequestSuccessCallbackResult
| UniApp.UploadFileSuccessCallbackResult
export type RequestOptionsResponseError = UniApp.GeneralCallbackResult
export type RequestTask = UniApp.RequestTask
export type UploadFileOption = UniApp.UploadFileOption
export interface HttpRequestOptions extends RequestConfig {
requestOptions: Partial<RequestOptions>
}
export interface RequestConfig {
baseUrl: string
requestHooks: RequestHooks
isReturnDefaultResponse: boolean
isTransformResponse: boolean
urlPrefix: string
ignoreCancel: boolean
withToken: boolean
isAuth: boolean
retryCount: number
retryTimeout: number
hasRetryCount?: number
}
export interface RequestHooks {
requestInterceptorsHook?(options: RequestOptions, config: RequestConfig): RequestOptions
responseInterceptorsHook?(response: ResponseResult, config: RequestConfig): any
responseInterceptorsCatchHook?(options: RequestOptions, error: any): any
}