更新记录
1.0.1(2025-01-10) 下载此版本
- 修复控制台提示
promise
异常问题。 -
新增
handleResponseErrorWithRetry
处理响应错误并重试方法。调用示例代码:- 请求库调用演示
// 假设 `response` 是响应错误的结果 if (response != null) { // 请求库实例设置的当前重试次数标识 this.attempts++; /** * this.retryRequest为请求库实例设置的存储当前重试请求 */ // #ifndef APP-ANDROID this.retryRequest = (url, options) => this.request(url, options); // #endif // #ifdef APP-ANDROID this.retryRequest = UTSAndroid.getKotlinFunction(request) as RetryFunction<RequestConfig, RequestSuccess<Response>> | null; // #endif if (this.interceptorManager.get(this.interceptorId)?.responseInterceptorErrorWithRetry == null) { return await this.interceptorManager.handleResponseError(response); } if (this.attempts <= retryTimes && this.retryRequest != null) { const withRetryOptions = { response, retryOptions: { retryTimes: this.attempts, retry: this.retryRequest as RetryFunction<RequestConfig, RequestSuccess<Response>> } as RetryOptions<RequestConfig, RequestSuccess<Response>> } as ResponseErrorCallbackOptions<RequestConfig, RequestSuccess<Response>> return (await this.interceptorManager.handleResponseErrorWithRetry(withRetryOptions)); } }
- 页面使用演示
// 假设httpService是初始化过的请求库实例 httpService.use({ ...其他拦截器方法 // 请求重试拦截 responseInterceptorErrorWithRetry: async (options): Promise<RequestSuccess<Response> | null> => { console.log('请求失败了可以重新尝试', options); return options.retryOptions.retry('https://test.api.fdproxy.cn/user/list', {} as RequestConfig); } } as RIInterceptor<RequestConfig, RequestSuccess<Response>>);
提示
请求重试拦截实例可以看文档最下面
完整自定义请求拦截示例
1.0.0(2025-01-06) 下载此版本
- 初始版本发布。
平台兼容性
Vue2 | Vue3 |
---|---|
× | √ |
App | 快应用 | 微信小程序 | 支付宝小程序 | 百度小程序 | 字节小程序 | QQ小程序 |
---|---|---|---|---|---|---|
HBuilderX 3.6.8,Android:支持,iOS:支持,HarmonyNext:不支持 | × | √ | × | × | × | × |
钉钉小程序 | 快手小程序 | 飞书小程序 | 京东小程序 | 鸿蒙元服务 |
---|---|---|---|---|
× | × | × | × | × |
H5-Safari | Android Browser | 微信浏览器(Android) | QQ浏览器(Android) | Chrome | IE | Edge | Firefox | PC-Safari |
---|---|---|---|---|---|---|---|---|
√ | √ | √ | √ | √ | √ | √ | √ | √ |
kux-request-interceptors
该插件是和请求库解耦的拦截器插件,可以适用于任何请求拦截封装场景,旨在为开发者们大量简化请求拦截的实现代码。
插件特色
- 适应任何请求库封装
- 简洁的API设计
- 支持泛型
- 和请求库完全解耦
基本用法
1.创建自定义的请求类,通过 use
方法注册拦截器,示例如下:
import { RIInterceptorManager, RIInterceptorManagerImpl, RIInterceptor } from '@/uni_modules/kux-request-interceptors';
export class HttpService {
private interceptorManager : RIInterceptorManager<RequestConfig, RequestSuccess<Response>>;
constructor() {
// 初始化拦截器
this.interceptorManager = new RIInterceptorManagerImpl<RequestConfig, RequestSuccess<Response>>();
}
/**
* 实现拦截器注册,方法名可以自定义,通过拦截器插件的 `use` 方法注册
*/
use(interceptor : RIInterceptor<RequestConfig, RequestSuccess<Response>>) : string {
return this.interceptorManager.use(interceptor);
}
/**
* 自定义请求
*/
async request(url: string, config: RequestConfig = {}): Promise<Response | null> {
// 这里通过插件的 `handleRequest` 方法注册请求拦截,拿到拦截处理后的请求参数
const beforeConfig = await this.interceptorManager.handleRequest(options);
// 这里写自己的请求逻辑代码,比如二次处理合并请求参数等等,此处省略
// 这里通过拦截器插件的 `handleRequestError` 方法注册请求错误拦截
if (error != null) {
const err = await this.interceptorManager.handleRequestError(error);
if (err != null) {
return Promise.reject(err) as Promise<IUniError>;
}
}
// 这里通过插件的 `handleResponse` 方法注册响应拦截
if (response != null && response.data != null) {
if (response.statusCode >= 200 && response.statusCode <= 299) {
return (await this.interceptorManager.handleResponse(response))!.data;
}
// 这里通过插件的 `handleResponseError` 方法注册响应错误
return (await this.interceptorManager.handleResponseError(response))!.data;
}
return Promise.resolve(null as any | null);
}
}
2.页面中使用自定义请求类
import { HttpService, RequestConfig, Data, Response } from '../../service/HttpService';
const httpService = new HttpService();
// 注册拦截器
httpService.use({
requestInterceptor: async (config: RequestConfig): Promise<RequestConfig> => {
console.log('进入请求拦截器', config);
config.data = {
a: 1
}
return config;
},
responseInterceptor: async (response): Promise<RequestSuccess<Response>> => {
console.log('进入响应拦截器', response);
if (response.data?.message != null) {
response.data!.message = '请求成功测试';
}
return response;
},
requestInterceptorError: async (error: IUniError): Promise<IUniError | null> => {
console.log('网络错误了', error);
return error;
},
responseInterceptorError: async (response): Promise<RequestSuccess<Response> | null> => {
console.log('请求失败了', response);
// Promise.reject('请求失败了哈哈哈');
return response;
},
responseInterceptorErrorWithRetry: async (options): Promise<RequestSuccess<Response> | null> => {
console.log('请求失败了可以重新尝试', options);
return options.retryOptions.retry('https://test.api.fdproxy.cn/user/list', {} as RequestConfig);
}
} as RIInterceptor<RequestConfig, RequestSuccess<Response>>);
// 发起请求测试
httpService.request('https://test.api.cn/user/list')
.then((response) => {
console.log(response);
if (response != null) {
// const res = response as Response;
const data = response.data;
if (data != null) {
console.log(data[0].name);
}
}
})
.catch((error) => {
console.log(error);
})
提示
上面的
RequestConfig
为自定义的请求参数类型定义,Response
为自定义的响应结果参数类型实现请求类时上下文类型一定要保持一致,比如实例化拦截器时
new RIInterceptorManagerImpl<T, R>
的T
对应请求参数类型,R
对应响应结果类型。请求重试拦截实例可以看文档最下面
完整自定义请求拦截示例
API
RIInterceptorManagerImpl
- 说明:拦截管理器实现类
- 类型:
class RIInterceptorManagerImpl<T, R>
RIInterceptorManagerImpl 方法说明
use
- 说明:注册拦截器
- 类型:
use (interceptor: RIInterceptor<T, R>): string
- 返回值:返回当前拦截器id
eject
- 说明:移除指定的拦截器
- 类型:
eject(id: string): void
clear
- 说明:清除所有的拦截器
- 类型:
clear(): void
get
- 说明:获取指定的拦截器
- 类型:
get(id: string): RIInterceptor<T, R> | null
- 返回值:返回拦截器实例,如果不存在返回null
handleRequest
- 说明:处理请求拦截
- 类型:
handleRequest(config: T): Promise<T>
handleResponse
- 说明:处理响应拦截
- 类型:
handleResponse(response: R): Promise<R>
handleRequestError
- 说明:处理请求错误拦截,一般是比如网络错误,请求地址错误等等场景
- 类型:
handleRequestError(error: IUniError): Promise<IUniError | null>
handleResponseError
- 说明:处理响应错误拦截,一般是比如接口参数错误,接口返回自定义错误等场景
- 类型:
handleResponseError(response: R): Promise<R | null>
handleResponseErrorWithRetry
- 说明:处理响应错误并重试,一般是比如自动续签token等类似场景使用。
- 类型:
handleResponseErrorWithRetry(options: ResponseErrorCallbackOptions<T, R>): Promise<R | null>;
ResponseErrorCallbackOptions 参数说明
- 说明:响应错误并重试函数参数
-
泛型参数:
ResponseErrorCallbackOptions<T, R>
T
请求参数类型R
响应结果类型
response
- 说明:重试回调的原始响应内容
- 类型:
R
retryOptions
- 说明:重试参数,包含
retryTimes
重试次数和retry
重试函数 - 类型:
RetryOptions<T, R>
RetryOptions 参数说明
- 说明:重试参数内容
-
泛型参数:
RetryOptions<T, R>
T
请求参数类型R
响应结果类型
retryTimes
- 说明:重试次数,重试次数会依此递减直至为0不再重试
- 类型:
number
retry
- 说明:发起重试的函数,也就是当前请求函数实例
- 类型:
RetryFunction<T, R>
RetryFunction 参数说明
- 说明:发起重试的函数类型
- 类型:
type RetryFunction<T, R> = (url: string, config: T) => Promise<R | null>
T
请求参数类型R
响应结果类型
完整自定义请求拦截示例
import { request as _request } from '@/uni_modules/kux-request-lite';
import { RIInterceptorManager, RIInterceptorManagerImpl, RIInterceptor, ResponseErrorCallbackOptions, RetryOptions, RetryFunction } from '@/uni_modules/kux-request-interceptors';
/**
* 自定义请求配置
*/
export type RequestConfig = {
data ?: any;
header ?: UTSJSONObject;
method ?: string;
timeout ?: number;
withCredentials ?: boolean;
firstIpv4 ?: boolean;
}
export type Data = {
id : number
name : string
age : number
}
export type Response = {
route ?: string
method ?: string
statusCode : number
message : string
data ?: Data[]
error ?: string
}
/**
* 使用拦截器请求服务演示类
*/
export class HttpService {
private interceptorManager : RIInterceptorManager<RequestConfig, RequestSuccess<Response>>;
// 记录已经重试的次数
private attempts : number = 0;
// 存储需要重试的函数
private retryRequest: RetryFunction<RequestConfig, RequestSuccess<Response>> | null;
// 记录当前拦截器唯一标识,后面用来获取当前拦截器使用
private interceptorId: string = '';
constructor() {
this.interceptorManager = new RIInterceptorManagerImpl<RequestConfig, RequestSuccess<Response>>();
this.retryRequest = null;
}
/**
* 实现拦截器注册
*/
use(interceptor : RIInterceptor<RequestConfig, RequestSuccess<Response>>) : string {
this.interceptorId = this.interceptorManager.use(interceptor);
return this.interceptorId;
}
async request(url : string, options : RequestConfig = {} as RequestConfig) : Promise<Response | null> {
const { retryTimes = 3 } = options;
const beforeConfig = await this.interceptorManager.handleRequest(options);
const { response, error } = await _request<Response>({
url: url,
data: beforeConfig.data,
header: beforeConfig.header,
method: beforeConfig.method,
timeout: beforeConfig.timeout,
withCredentials: beforeConfig.withCredentials,
firstIpv4: beforeConfig.firstIpv4,
} as RequestOptions<Response>);
if (error != null) {
const err = await this.interceptorManager.handleRequestError(error);
if (err != null) {
return Promise.reject(err) as Promise<IUniError>;
}
}
if (response != null && response.data != null) {
if (response.statusCode >= 200 && response.statusCode <= 299) {
return (await this.interceptorManager.handleResponse(response))!.data;
}
this.attempts++;
// #ifndef APP-ANDROID
this.retryRequest = (url, options) => this.request(url, options);
// #endif
// #ifdef APP-ANDROID
this.retryRequest = UTSAndroid.getKotlinFunction(request) as RetryFunction<RequestConfig, RequestSuccess<Response>> | null;
// #endif
if (this.interceptorManager.get(this.interceptorId)?.responseInterceptorErrorWithRetry == null) {
return await this.interceptorManager.handleResponseError(response);
}
if (this.attempts <= retryTimes && this.retryRequest != null) {
const withRetryOptions = {
response,
retryOptions: {
retryTimes: this.attempts,
retry: this.retryRequest as RetryFunction<RequestConfig, RequestSuccess<Response>>
} as RetryOptions<RequestConfig, RequestSuccess<Response>>
} as ResponseErrorCallbackOptions<RequestConfig, RequestSuccess<Response>>
return (await this.interceptorManager.handleResponseErrorWithRetry(withRetryOptions));
}
}
return Promise.resolve(null as any | null);
}
}
结语
kux 不生产代码,只做代码的搬运工,致力于提供uts 的 js 生态轮子实现,欢迎各位大佬在插件市场搜索使用 kux 生态插件:https://ext.dcloud.net.cn/search?q=kux
友情推荐
- TMUI4.0:包含了核心的uts插件基类.和uvue组件库
- GVIM即时通讯模版:GVIM即时通讯模版,基于uni-app x开发的一款即时通讯模版
- t-uvue-ui:T-UVUE-UI是基于UNI-APP X开发的前端UI框架
- UxFrame 低代码高性能UI框架:【F2图表、双滑块slider、炫酷效果tabbar、拖拽排序、日历拖拽选择、签名...】UniAppX 高质量UI库
- wx-ui 基于uni-app x开发的高性能混合UI库:基于uni-app x开发的高性能混合UI库,集成 uts api 和 uts component,提供了一套完整、高效且易于使用的UI组件和API,让您以更少的时间成本,轻松完成高性能应用开发。
- firstui-uvue:FirstUI(unix)组件库,一款适配 uni-app x 的轻量、简洁、高效、全面的移动端组件库。
- easyXUI 不仅仅是UI 更是为UniApp X设计的电商模板库:easyX 不仅仅是UI库,更是一个轻量、可定制的UniAPP X电商业务模板库,可作为官方组件库的补充,始终坚持简单好用、易上手