鸿蒙【ArkTS】封装数据请求HTTP 使用装饰器进行配置化引入接口

这篇具有很好参考价值的文章主要介绍了鸿蒙【ArkTS】封装数据请求HTTP 使用装饰器进行配置化引入接口。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

鸿蒙【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

到了这里,关于鸿蒙【ArkTS】封装数据请求HTTP 使用装饰器进行配置化引入接口的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【HarmonyOS】【ArkTS】如何使用HTTP网络请求获取动态数据刷新UI界面

    【】 HttpRequest、ArkTS、网络数据请求、@ohos.net.http 【前言】 在使用ArkTS开发HarmonyOS应用时,需要调用HTTP网络请求 @ohos.net.http 动态获取数据,进行UI列表刷新,这想必是应用开发最常见的功能。但是根据官网网络请求的示例代码进行功能开发时,封装方法进行HTTP请求后

    2024年02月08日
    浏览(47)
  • 鸿蒙harmony--HTTP数据请求的简单使用

     不得不承认,年龄越大性格就越简单,更喜欢安静,不喜欢去了解别人,也不想被了解,只想静静的做自己喜欢的事…… 目录 一,场景介绍 二,接口说明 三,http请求使用 应用通过HTTP发起一个数据请求,支持常见的GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT方法。 HT

    2024年01月20日
    浏览(42)
  • 【HarmonyOS开发】ArkTs使用Http封装

    @ohos/axios @ohos/retrofit @ohos/httpclient @ohos.net.http 本模块提供HTTP数据请求能力。应用可以通过HTTP发起一个数据请求,支持常见的GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT方法。 http.createHttp(创建请求实例任务); request(请求); destroy(中断请求); on(订阅HTTP Response H

    2024年01月22日
    浏览(47)
  • Arkts http数据请求

    使用Arkts功能需要申请ohos.permission.INTERNET权限。即在module.json5文件中申明网络访问权限:ohos.permission.INTERNET。如下 Arkts http数据请求功能主要由http模块提供。具体接口说明如下表。 接口名 功能描述 createHttp() 创建一个http请求。 request() 根据URL地址,发起HTTP网络请求。 destroy

    2024年02月04日
    浏览(57)
  • HarmonyOS ArkTS HTTP数据请求(九)

    日常生活中我们使用应用程序看新闻、发送消息等,都需要连接到互联网,从服务端获取数据。例如,新闻应用可以从新闻服务器中获取最新的热点新闻,从而给用户打造更加丰富、更加实用的体验。 那么要实现这样一种能实时从服务端获取数据的场景,就依赖于HTTP数据请

    2024年02月03日
    浏览(54)
  • 鸿蒙应用开发之HTTP数据请求

    日常生活中我们使用应用程序看新闻、发送消息等,都需要连接到互联网,从服务端获取数据。例如,新闻应用可以从新闻服务器中获取最新的热点新闻,从而给用户打造更加丰富、更加实用的体验。 那么要实现这样一种能实时从服务端获取数据的场景,就依赖于HTTP数据请

    2024年02月05日
    浏览(47)
  • 鸿蒙HarmonyOS-HTTP网络数据请求

    应用可以通过HTTP发起一个数据请求,支持常见的GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT方法。 亲爱的读者: 首先,我要感谢您抽出宝贵的时间阅读这篇文章。我深知,您的每一分每一秒都是宝贵的。为此,我在创作这篇文章时付出了巨大的努力,力求为您提供最具价

    2024年01月16日
    浏览(72)
  • 鸿蒙ArkTS小短剧开源项目进行中

    使用ArtTS语言,API9以上,HarmonyOS系统的短剧开源代码,使用GSYVideoPlayer作为核心播放器的小短剧。主要以ArkTS,ArkUI编写为主,拥有市面上的短剧页面。 推荐页面,主要随机推荐热门的小短剧并播放 短剧页面,主要是对短剧类型进行了分类,可供选择。 收藏界面,主要是对自

    2024年04月16日
    浏览(35)
  • 鸿蒙OS开发实战:【网络管理HTTP数据请求】

    应用通过HTTP发起一个数据请求,支持常见的GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT方法。 HTTP数据请求功能主要由http模块提供。 使用该功能需要申请ohos.permission.INTERNET权限。 涉及的接口如下表,具体的接口说明请参考API文档。 接口名 功能描述 createHttp() 创建一个ht

    2024年04月29日
    浏览(35)
  • 【鸿蒙(HarmonyOS)】UI开发的两种范式:ArkTS、JS(以登录界面开发为例进行对比)

    之后关于HarmonyOS技术的分享,将会持续使用到以下版本 HarmonyOS:3.1/4.0 SDK:API 9 Release Node.js:v14.20.1 DevEco Studio: 3.1.0 HarmonyOS应用的UI开发依赖于 方舟开发框架(简称ArkUI) 。 根据官方介绍,ArkUI提供了UI语法、丰富的UI功能(组件、布局、动画以及交互事件),以及实时界面

    2024年02月08日
    浏览(68)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包