更新记录
1.0.5(2025-06-09) 下载此版本
- 请求只支持await调用 不支持链式调用 request().then()这种方式
const request = () ....
支持 const data = await request();
不支持 request().then(res => {...})
1.0.4(2025-06-09) 下载此版本
- 请求只支持await调用 不支持链式调用 request().then()这种方式
const request = () ....
// 支持 const data = await request();
// 不支持 request().then(res => {...})
1.0.3(2025-06-09) 下载此版本
- 加入更多请求示例 见index.uvue
- 提示各位开发者 UTS是一种强类型的编程语言,不要用TS的逻辑往UTS上套
如果你的type定义为
export type APIResponse = {
code: string;
message: string;
data: any | null; // data没有用?标识
i18n?: string;
}
response = {code: '0000', message: '请求成功'} UTS会报错error message invalid json TS正常data为undefind
response = {code: '0000', message: '请求成功', data: null} UTS与TS均正常
如果你的data没有用?标识,那么服务端返回包装类中就必须要有data,如果没有data属性,那么就会报error message invalid json错误
export type APIResponse = {
code: string;
message: string;
data?: any | null; // data使用?标识
i18n?: string;
}
response = {code: '0000', message: '请求成功'} 不报错
response = {code: '0000', message: '请求成功', data: null} 不报错
同样的在开发页面的时候 也需要注意这种错误
如果你碰到了error message invalid json这种错误 请排查自己的Type定义
查看更多
平台兼容性
uni-app x
Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
---|---|---|---|---|---|
√ | √ | 5.0 | 12 | - | √ |
其他
多语言 | 暗黑模式 | 宽屏模式 |
---|---|---|
× | × | √ |
xsd-request
- Android/IOS已通过自定义基座测试 HarmonyNext已通过模拟器测试 真机尚不确定 欢迎小伙伴们反馈。
- 有任何问题可直接邮件至liujiaxin@xinshidaike.com联系我
- 如果觉得好用,请给我一个五星好评吧~
- 同时该插件配套的一键生成代码工具正在制作中,后端接口需要符合Swagger 3.0规范(类似Alova的代码生成),敬清期待~
使用示例
import { refreshToken } from './api/api';
import { createXRequest, XBaseRequestOptions, XRequestOptions } from '@/uni_modules/xsd-request';
export type APIResponse = {
code: string;
message: string;
data?: any | null;
i18n?: string;
}
// #ifdef APP-ANDROID
@Suppress("LABEL_NAME_CLASH")
// #endif
async function _xRequest<T>(instanceConfig: RequestOptions<any>): Promise<T>{
return createXRequest<APIResponse>(
{
baseUrl: 'http://192.168.6.6:6080/x-system-server',
timeout: 1000,
header: {
a: '1'
}
} as XBaseRequestOptions
, {
onRequest: function(config: RequestOptions<any>) {
// 演示方便 token存在Storage中 请自行替换为更可靠的存储方式
config.header?.set('Authorization', `Bearer ${uni.getStorageSync('x-accessToken')}`)
return config;
},
onRequestEnd: async function(response: RequestSuccess<APIResponse>) {
if(401 == response.statusCode){
// 无权限/鉴权无效/鉴权过期 无感刷新Token
await refreshToken();
console.log('已刷新鉴权!');
// 返回null 请求重试
return null;
}
return 200 == response.statusCode;
},
onRequestError: function(error: IUniError, response: RequestSuccess<APIResponse> | null) {
if(null != response){
uni.showToast({
title: `请求状态码[${response.statusCode}]`
})
}else{
/**
* 如果uni.request进入了fail 则response为null
* 通常是网络原因 无法请求至指定接口
* https://doc.dcloud.net.cn/uni-app-x/api/request.html#requestfail-values
*/
uni.showToast({
title: `请求错误码[${error.errCode}]`
})
}
},
onRequestMonitor: function(response: APIResponse) {
return response.code == '0000';
},
onRequestMonitorError: function(response: APIResponse) {
// 请求成功 但业务失败
uni.showToast({
title: `[${response.code}]${response.message}`,
// 国际化提示
// title: $t({response?.i18n})
})
},
onSuccess: function(response: APIResponse): any | null {
if(null == response.data){
return null;
}
return response.data as any | undefined
}
} as XRequestOptions<APIResponse>
, instanceConfig
) as Promise<T>
}
export async function xRequest<T>(instanceConfig: RequestOptions<any>): Promise<T>{
// #ifdef APP-ANDROID
// 解决Android泛型转换失败问题
// 此处代码暂时无法移入到onSuccess中 Android会编译错误 等待官方修复 这样也可以正常使用
const v = await _xRequest<T>(instanceConfig) as any | null
if(null == v){
return null as T;
}
return JSON.parse<T>(JSON.stringify(v)) as T;
// #endif
// #ifndef APP-ANDROID
return _xRequest<T>(instanceConfig);
// #endif
}
/**
* 全局请求配置 对齐官方 额外加入baseUrl
* https://doc.dcloud.net.cn/uni-app-x/api/request.html
*/
export type XBaseRequestOptions = {
baseUrl: string;
header ?: UTSJSONObject;
timeout ?: number;
withCredentials ?: boolean;
firstIpv4 ?: boolean;
}
/**
* success响应 / fail响应
*/
export type XAllResponse<APIResponse> = {
response: RequestSuccess<APIResponse> | null;
error: IUniError | null;
}
/**
* 请求钩子
*/
export type XRequestOptions<APIResponse> = {
/**
* 请求前钩子
*
* 支持uni.request全部参数
* https://doc.dcloud.net.cn/uni-app-x/api/request.html
*/
onRequest: (config: RequestOptions<any>) => RequestOptions<any>;
/**
* 请求结束后钩子
*
* 用于http是否成功
*/
onRequestEnd: (response: RequestSuccess<APIResponse>) => Promise<boolean | null>;
/**
* 请求失败钩子
*
* 由onRequestEnd返回false调用
*/
onRequestError: (error: IUniError, response: RequestSuccess<APIResponse> | null) => void;
/**
* 业务是否成功钩子
*
* 由onRequestEnd返回true调用
*/
onRequestMonitor: (response: APIResponse) => boolean;
/**
* 业务错误钩子
*
* 由onRequestMonitor返回false调用
*
*/
onRequestMonitorError: (response: APIResponse) => void;
/**
* 业务成功钩子
*
* 由onRequestMonitor返回ture调用
* 用于提出出包装类中的数据
*/
onSuccess: (response: APIResponse) => any | null;
}
export interface IXError extends IUniError {};
import { xRequest } from "../request";
export type XToken = {
accessToken : string;
refreshToken : string;
}
export const storageToken = (accessToken: string, refreshToken: string) => {
uni.setStorageSync('x-accessToken', accessToken);
uni.setStorageSync('x-refreshToken', refreshToken);
}
export const doLogin = async () => {
return xRequest<XToken>({
url: '/auth-free/accountLogin',
method: 'POST',
data: {
account: 'super-admin',
password: '123456'
}
} as RequestOptions<any>)
}
export const refreshToken = async () => {
const _refreshToken = uni.getStorageSync('x-refreshToken');
const data = await xRequest<XToken>({
url: '/auth-free/refreshToken',
method: 'POST',
data: {
refreshToken: _refreshToken
}
} as RequestOptions<any>);
storageToken(data.accessToken, data.refreshToken);
}
export type Info = {
id: string;
}
export const authApi = () => {
return xRequest<Info>({
url: '/admin/tokenGetInfo',
method: 'GET'
} as RequestOptions<any>)
}
export const authNull = () => {
return xRequest<void>({
url: '/admin/null',
method: 'GET'
} as RequestOptions<any>)
}
type ArrayData = {
id: number;
value: string;
}
export const authArray = () => {
return xRequest<ArrayData[]>({
url: '/admin/array',
method: 'GET'
} as RequestOptions<any>)
}
export type Params = {
params1: string;
params2: string;
}
/**
* https://doc.dcloud.net.cn/uni-app-x/api/request.html
* app-android端 参数只能为UTSJSONObject或者string
* app-android平台从 4.51版本开始支持ArrayBuffer, app-ios平台从 4.61版本开始支持ArrayBuffer
*/
export const authParams = (params: Params) => {
return xRequest<Params>({
url: '/admin/params',
method: 'POST',
data: JSON.parse<UTSJSONObject>(JSON.stringify(params))
} as RequestOptions<any>)
}
export const authParams2 = (params: UTSJSONObject) => {
return xRequest<Params>({
url: '/admin/params',
method: 'POST',
data: params
} as RequestOptions<any>)
}
<template>
<view>
<button @click="b1">调用登录接口</button>
<button @click="b2">调用鉴权接口</button>
<button @click="b22">调用返回null接口</button>
<button @click="b23">调用返回Array接口</button>
<input style="height: 50px; border: 1px solid #ddd;" v-model="params.params1" placeholder="参数1"/>
<input style="height: 50px; border: 1px solid #ddd;" v-model="params.params2" placeholder="参数2"/>
<button @click="b24">接口传参示例1</button>
<button @click="b25">接口传参示例2</button>
<button @click="b3">删除accessToken(模拟未鉴权)</button>
<button @click="b4">修改assessToken(模拟鉴权过期或无效)</button>
<button @click="b5">清空全部token</button>
<button @click="b6">UTS强类型示意</button>
</view>
</template>
<script lang="uts" setup>
import { Params, authApi, authArray, authNull, authParams, authParams2, doLogin, storageToken } from '@/service';
const params = reactive<Params>({
params1: '',
params2: ''
})
const b1 = async () => {
const data = await doLogin();
// 如果请求失败 代码会被throw error阻断 下方代码不会执行
console.log('登录接口数据=', data);
storageToken(data.accessToken, data.refreshToken);
/*
14:45:11.788 登录接口数据= [XToken] {accessToken: "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJETC1YU0QiLCJpYXQiOjE3NDk0NTE1MTEsImV4cCI6MTc0OTQ1ODcxMSwianRpIjoiMSJ9.4VMEi-c7V6PEKV_XO1R55erKejgjvAspSanAZm_yvPI", refreshToken: "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJETC1YU0QiLCJpYXQiOjE3NDk0NTE1MTEsImV4cCI6MTc0OTUzNzkxMSwianRpIjoiMSJ9.whTKvqTlMvD0N8Dzo7YaedeYGj_qs30OO_psCnpaYyE"} at pages/index/index.uvue:28
*/
}
const b2 = async () => {
const data = await authApi();
console.log('鉴权接口数据=', data);
uni.showToast({
title: data.id
})
/*
14:45:29.186 鉴权接口数据= [Info] {id: "1"} at pages/index/index.uvue:34
*/
}
const b22 = async () => {
await authNull();
console.log('已调用返回null的接口')
uni.showToast({
title: '已调用'
})
/*
14:45:45.447 已调用返回null的接口 at pages/index/index.uvue:42
*/
}
const b23 = async () => {
const data = await authArray();
console.log('返回array接口=', data)
console.log('array[0]=', data[0])
console.log('array[1]=', data[1])
uni.showToast({
title: JSON.stringify(data)
})
/*
14:45:58.056 返回array接口= [Array] [ {id: 2, value: "A2"}, {id: 2, value: "A2"} ] at pages/index/index.uvue:50
14:45:58.056 array[0]= [ArrayData] {id: 2, value: "A2"} at pages/index/index.uvue:51
14:45:58.056 array[1]= [ArrayData] {id: 2, value: "A2"} at pages/index/index.uvue:5
*/
}
const b24 = async () => {
/**
* authParams方法会将params转换为UTSJSONObject
*/
const data = await authParams(params);
console.log('传参示例1=', data)
uni.showToast({
title: JSON.stringify(data)
})
/*
14:46:28.783 传参示例1= [Params] {params1: "参数1", params2: "参数22222222"} at pages/index/index.uvue:63
*/
}
const b25 = async () => {
const p = {
params1: params.params1,
params2: params.params2
} as UTSJSONObject
const data = await authParams2(p);
console.log('传参示例2=', data)
uni.showToast({
title: JSON.stringify(data)
})
/*
14:46:39.646 传参示例2= [Params] {params1: "参数1", params2: "参数22222222"} at pages/index/index.uvue:76
*/
}
const b3 = () => {
uni.removeStorageSync('x-accessToken');
console.log('已删除accessToken')
uni.showToast({
title: '已删除'
})
}
const b4 = () => {
uni.setStorageSync('x-accessToken', '1111');
console.log('已修改accessToken')
uni.showToast({
title: '已修改'
})
}
const b5 = () => {
uni.clearStorageSync();
console.log('已清空Storage')
uni.showToast({
title: '已清空'
})
}
type A = {
code: string;
data: string;
}
type B = {
code: string;
data?: string;
}
const b6 =() => {
// UTS与TS均不报错 UTS的data为null TS的data为undefined
console.log(JSON.parse<B>(JSON.stringify({code: '0000'})));
// UTS报错 TS不报错 data为undefined
console.log(JSON.parse<A>(JSON.stringify({code: '0000'})));
}
</script>
<style>
</style>
服务端示例代码
@GetMapping("/null")
public void nullGet() {
}
@GetMapping("/array")
public JSONArray authArray() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", 1);
jsonObject.put("value", "A1");
JSONArray jsonArray = new JSONArray();
jsonArray.add(jsonObject);
jsonObject.put("id", 2);
jsonObject.put("value", "A2");
jsonArray.add(jsonObject);
return jsonArray;
}
@PostMapping("/params")
public JSONObject params(@RequestBody JSONObject jsonObject) {
return jsonObject;
}
友情链接
- UxFrame 低代码高性能UI框架:UniAppX 高质量UI库