鸿蒙【ArkTS】封装数据请求HTTP 使用装饰器进行配置化引入接口
官方API文档:数据请求HTTP
实现步骤:
一、统一接口请求结果
export class ApiResult {
code : string
msg ?: string
data ?: any
}
二、网络请求配置类
/**
* <pre>
* @desc : 网络请求配置
* </pre>
*/
export interface RequestOptions {
/**
* Request url.
*/
url?: string;
/**
* Request method.
*/
method?: RequestMethod; // default is GET
/**
* Additional data of the request.
* extraData can be a string or an Object (API 6) or an ArrayBuffer(API 8).
*/
extraData?: string | Object | ArrayBuffer;
/**
* Request url queryParams .
*/
queryParams ?: Record<string, string>;
/**
* HTTP request header.
*/
header?: Object; // default is 'content-type': 'application/json'
}
export enum RequestMethod {
OPTIONS = "OPTIONS",
GET = "GET",
HEAD = "HEAD",
POST = "POST",
PUT = "PUT",
DELETE = "DELETE",
TRACE = "TRACE",
CONNECT = "CONNECT"
}
三、网络请求核心类 引用官方Api
import http from '@ohos.net.http';
import { RequestOptions } from './RequestOptions';
import { ApiResult } from '../ApiResult/ApiResult';
// 引入弹窗
import PreferenceUtil from '../../utils/PreferenceUtil'
import promptAction from '@ohos.promptAction';
import { LoadingProgressDialog } from '../../utils/LoadingProgressDialog';
import router from '@ohos.router';
/**
* Http请求器
*/
export class HttpCore {
loadingDialog: CustomDialogController = new CustomDialogController({
builder: LoadingProgressDialog(),
alignment:DialogAlignment.Center,
autoCancel: true,
customStyle: true
});
/**
* 发送请求
* @param requestOption
* @returns Promise
*/
request(requestOptions: RequestOptions): Promise<ApiResult> {
let p = new Promise<ApiResult>(async (resolve, reject) => {
// 每一个httpRequest对应一个HTTP请求任务,不可复用
let httpRequest = http.createHttp();
let token : string = await getToken();
let promise = httpRequest.request(requestOptions.url, {
method: requestOptions.method,
connectTimeout: 60000,
readTimeout: 60000,
header:{
'Content-Type': 'application/json',
'token': token,
'client_type': 'HarmonyOS'
},
extraData: requestOptions.extraData
});
promise.then((data) => {
//TODO:此处补充数据拆包的操作
let resultObj = JSON.parse(data.result.toString());
//弹窗提示接口返回msg
setTimeout(() => {
promptAction.showToast({
message: resultObj.msg
})
}, 500);
//如果业务码为20000 则返回ApiReslut
if (resultObj.code == 20000) {
console.log(JSON.stringify(resultObj))
resolve(resultObj);
}
if (resultObj.code == 0){
router.replaceUrl({
url: "pages/MainPage/Login"
}).then(() => {
console.log('router successful')
}).catch(err => {
console.log('router err')
})
}
//如果返回数据包含token信息 则刷新token
if (resultObj.token != undefined) {
PreferenceUtil.putPreference('token',resultObj.token)
}
}).catch((err) => {
//这里做全局异常统一处理 根据Http状态码做出处理
console.info('error:' + JSON.stringify(err));
reject(err);
});
httpRequest.destroy();
})
return p;
}
}
async function getToken(): Promise<string> {
return new Promise<string>(async (resolve, reject) => {
try {
const data = await PreferenceUtil.getPreference('token');
if (typeof data === 'string') {
resolve(data);
} else {
reject(new Error('Invalid token'));
}
} catch (err) {
reject(err);
}
});
}
export const httpCore = new HttpCore();
四、导出对外工具类
import { RequestMethod, RequestOptions } from './RequestOptions';
import { httpCore } from './HttpCore';
import { ApiResult } from '../ApiResult/ApiResult';
/**
* <pre>
* @desc : 对外工具包
* </pre>
*/
export class HttpUtil {
private static mInstance: HttpUtil;
// 防止实例化
private constructor() {
}
static getInstance(): HttpUtil {
if (!HttpUtil.mInstance) {
HttpUtil.mInstance = new HttpUtil();
}
return HttpUtil.mInstance;
}
request (option: RequestOptions): Promise<ApiResult> {
return httpCore.request(option);
}
/**
* 封装Post网络请求
* @param option
* @returns
*/
Post(option:RequestOptions){
if(option != null){
option.method = RequestMethod.POST
}
return this.request(option);
}
/**
* 封装Get网络请求
* @param option
* @returns
*/
Get(option:RequestOptions){
if(option != null){
option.method = RequestMethod.GET
}
return this.request(option);
}
}
export const httpUtil = HttpUtil.getInstance();
五、利用装饰器实现AOP效果
import { ApiResult } from '../ApiResult/ApiResult';
import { httpUtil } from '../Http/HttpUtil';
import { RequestOptions } from '../Http/RequestOptions';
/**
* 利用Map保存参数和值的映射关系 为避免参数名及方法名重复 采用组合Key的方法
*/
type FunParamMapKey = {
target: Object; //所在类
methodName: string; //所在方法
index: number; //参数名索引值
}
let funParamMap = new Map<string, string>();
// @Get注解 拿到url 从函数的@Param拿到参数名及参数值 利用HttpUtil进行网络请求
//Get 需要拼接URl
export function Get(url: string) {
return function (target: any, methodName: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
let URL: string = url;
let options: RequestOptions = {
url: URL,
queryParams: {}
};
descriptor.value = async function (...args: any[]) {
//对于方法中的每一个(methodName,arg)遍历加入到网络请求配置中
args.forEach((arg, index) => {
// 通过已知的信息构造组合Key对象
let obj: FunParamMapKey = { target: target, methodName: methodName, index: index };
// 通过组合Key(通过对内容的比较而不是值 节省内存)从内存map中获取@Param修饰的内容
let paramName = funParamMap[JSON.stringify(obj)];
// 将正确的参数名及值添加至网络请求参数中
if (typeof paramName !== 'undefined') {
if (typeof arg === 'string' || typeof arg === 'object' || arg instanceof ArrayBuffer || typeof arg === 'number') {
options.queryParams[paramName] = arg
} else {
console.log('参数类型不对')
throw new Error(`Invalid parameter type at index ${index}.`);
}
}
});
//拼接请求参数
const urlParams = Object.keys(options.queryParams).map(key => `${key}=${options.queryParams[key]}`).join('&')
console.log('urlParams:', urlParams)
if (URL.includes("?")) {
options.url = `${URL}${urlParams}`
} else {
options.url = `${URL}?${urlParams}`
}
const p = new Promise<ApiResult>((resolve, reject) => {
httpUtil.Get(options).then((response) => {
const result: ApiResult = response;
resolve(result);
}).catch((error) => {
reject(error);
});
});
return await p;
};
};
}
// @Post注解 拿到url 从函数的@Param拿到参数名及参数值 利用HttpUtil进行Post网络请求
export function Post(url: string) {
return function (target: any, methodName: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
let options: RequestOptions = {
url: url,
extraData: {}
};
descriptor.value = async function (...args: any[]) {
//对于方法中的每一个(methodName,arg)遍历加入到网络请求配置中
args.forEach((arg, index) => {
console.log("参数值",JSON.stringify(arg))
// 通过已知的信息构造组合Key对象
let obj: FunParamMapKey = { target: target, methodName: methodName, index: index };
// 通过组合Key(通过对内容的比较而不是值 节省内存)从内存map中获取@Param修饰的内容
let paramName = funParamMap[JSON.stringify(obj)];
console.log("参数名:",paramName)
// 将正确的参数名及值添加至网络请求参数中
if (typeof paramName !== 'undefined') {
if (typeof arg === 'string' || typeof arg === 'object' || arg instanceof ArrayBuffer) {
options.extraData[paramName] = arg;
} else {
throw new Error(`Invalid parameter type at index ${index}.`);
}
}else {
//如果获取不到形参名 及未被@Param标记 并且参数的类型是对象
if (typeof arg === 'object') {
options.extraData = JSON.stringify(arg)
}
}
});
console.log('extraData', JSON.stringify(options.extraData))
const p = new Promise<ApiResult>((resolve, reject) => {
httpUtil.Post(options).then((response) => {
const result: ApiResult = response;
resolve(result);
}).catch((error) => {
reject(error);
});
});
return await p;
};
};
}
/**
* @Param 注解将想要获取的Param添加至内存Map中
* @param paramName
* @returns
*/
export function Param(paramName: string) {
return function (target: any, methodName: string, parameterIndex: number) {
let obj: FunParamMapKey = { target: target, methodName: methodName, index: parameterIndex };
funParamMap[JSON.stringify(obj)] = paramName;
};
}
使用示例:
import{Post, Param} from './aop/aop'
import { ApiResult } from './ApiResult/ApiResult';
export class LoginApi {
@Post("http://localhost:8080/login")
//自定义@Param 作用:获取形参 便于映射到extraData
login(@Param("username") username: string, @Param("password") password: string):Promise<ApiResult> {
return
}
}
export const loginApi = new LoginApi();
import{Post,Get, Param} from './aop/aop'
import { ApiResult } from './ApiResult/ApiResult';
export class MenuApi {
@Get("http://localhost:8080/api/menu/getMenuTree")
getMenuTree():Promise<ApiResult> {
return
}
@Get("http://localhost:8080/api/menu/getPermTree")
getPermsSelectTree():Promise<ApiResult> {
return
}
//@Get中的@Param 可以将形参拼接到URl中
@Get("http://localhost:8080/api/menu/get")
getMenuById(@Param("Id") id : number):Promise<ApiResult> {
return
}
}
export const menuApi = new MenuApi();
import { RoleModel } from '../models/RoleModel';
import{Post,Get, Param} from './aop/aop'
import { ApiResult } from './ApiResult/ApiResult';
export class RoleApi{
/**
* 获取所有角色
* @returns
*/
@Get("http://localhost:8080/api/role/getAllRole")
getAllRole():Promise<ApiResult> {
return
}
//可以直接Post对象
@Post("http://localhost:8080/api/role/updateRole")
updateRole(role : RoleModel):Promise<ApiResult> {
return
}
}
export const roleApi = new RoleApi();
文章来源地址https://www.toymoban.com/news/detail-855850.html
文章来源:https://www.toymoban.com/news/detail-855850.html
到了这里,关于鸿蒙【ArkTS】封装数据请求HTTP 使用装饰器进行配置化引入接口的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!