HarmonyOS 基于Network Kit封装的网络请求工具

Support

  • 泛型返回结果
  • 拦截器实现
  • 全局配置header
  • 独立设置header参数

Features

  • 缓存功能
  • 取消请求

配置类型定义

基础配置

ArkTS 复制代码
export interface NetConfig {
  baseURL: string;
  timeout?: number;
  headers?: Record<string, string>;
  statusHandlers?: Record<number, string>; // 状态码映射
}

定义 Response 泛型基类

ArkTS 复制代码
export interface BaseResponse<T> {
  requestUrl: string,
  requestMethod: http.RequestMethod,
  requestHeaders: Record<string, string>,
  requestBody: string,
  code: number
  data: T
}

拦截器上下文接口

ArkTS 复制代码
interface InterceptorContext {
  url: string;
  method: http.RequestMethod;
  headers: Record<string, string>;
  data?: object;
};

拦截器基类

ArkTS 复制代码
export abstract class Interceptor {
  // 请求前调用
  async onRequest?(context: InterceptorContext): Promise<void> {
    // 子类可重写此方法
  }

  // 响应后调用
  async onResponse?<T>(response: BaseResponse<T>, context: InterceptorContext): Promise<void> {
    // 子类可重写此方法
  }
}

网络初始化配置类

ArkTS 复制代码
export class NetManager {
  static instance: NetManager;
  private config: NetConfig;

  static init(config: NetConfig) {
    if (!NetManager.instance) {
      NetManager.instance = new NetManager(config);
    }
  }

  private constructor(config: NetConfig) {
    this.config = config;
  }

  getConfig(): NetConfig {
    return this.config;
  }
}

请求接口类

ArkTS 复制代码
interface RequestOptions {
  cacheKey?: string; // 缓存标识
  showLoading?: boolean; // 显示加载框
  headers?: Record<string, string>;
};

请求工具类

ArkTS 复制代码
export class NetUtils {
  static globalInterceptors: Interceptor[] = [];

  static async request<T>(
    method: http.RequestMethod,
    url: string,
    data?: Record<string, string | number | boolean | RequestDataArray>,
    options?: RequestOptions,
  ): Promise<BaseResponse<T>> {
    const config = NetManager.instance.getConfig();
    const fullUrl = `${config.baseURL}${url}`;
    const req = http.createHttp();
    // 合并请求头:全局配置 < 单独设置的headers
    const mergedHeaders: Record<string, string> = {};

    // 手动合并全局headers(使用Object.keys)
    if (config.headers) {
      const globalHeaderKeys = Object.keys(config.headers);
      for (let i = 0; i < globalHeaderKeys.length; i++) {
        const key = globalHeaderKeys[i];
        mergedHeaders[key] = config.headers[key];
      }
    }

    // 手动合并单独设置的headers(使用Object.keys)
    if (options?.headers) {
      const optionHeaderKeys = Object.keys(options.headers);
      for (let i = 0; i < optionHeaderKeys.length; i++) {
        const key = optionHeaderKeys[i];
        mergedHeaders[key] = options.headers[key];
      }
    }

    // 请求上下文
    let context: InterceptorContext = {
      url: fullUrl,
      method,
      headers: config.headers ?? {},
      data
    };

    try {
      // 请求拦截器(添加全局Header)
      context = await NetUtils.handleRequestInterceptors(context);

      // 执行请求
      const response = await req.request(fullUrl, {
        method,
        header: context.headers,
        extraData: data,
        expectDataType: http.HttpDataType.OBJECT,
        readTimeout: config.timeout ?? 30000,
      });

      // 状态码处理(统一错误码)
      if (config.statusHandlers?.[response.responseCode]) {
        throw new Error(config.statusHandlers[response.responseCode]);
      }

      // 响应数据处理
      const result = response.result as T;
      const baseResponse: BaseResponse<T> = {
        requestUrl: fullUrl,
        requestMethod: method,
        requestHeaders: context.headers,
        requestBody: JSON.stringify(data),
        code: response.responseCode,
        data: result,
      };

      // 响应拦截器处理
      await NetUtils.handleResponseInterceptors(baseResponse, context);

      hilog.info(0, 'NetUtils', 'request', JSON.stringify(baseResponse))
      return baseResponse;
    } finally {
      req.destroy();
    }
  }

  static async handleRequestInterceptors(ctx: InterceptorContext) {
    for (const interceptor of NetUtils.globalInterceptors) {
      if (interceptor.onRequest) {
        await interceptor.onRequest(ctx);
      }
    }
    return ctx;
  }

  static async handleResponseInterceptors<T>(response: BaseResponse<T>, ctx: InterceptorContext) {
    for (const interceptor of NetUtils.globalInterceptors) {
      if (interceptor.onResponse) {
        await interceptor.onResponse(response, ctx);
      }
    }
  }

  // 添加全局拦截器
  static addInterceptor(interceptor: Interceptor) {
    NetUtils.globalInterceptors.push(interceptor);
  }
}

创建具体的拦截器子类

Log拦截器

ArkTS 复制代码
export class LoggingInterceptor extends Interceptor {
  async onRequest(context: InterceptorContext): Promise<void> {
    hilog.info(0, 'LoggingInterceptor', 'Request: ' + context.url);
  }

  async onResponse<T>(response: BaseResponse<T>): Promise<void> {
    hilog.info(0, 'LoggingInterceptor', 'Response Code: ' + response.code);
  }
}

Token拦截器 在header中添加token

ArkTS 复制代码
export class TokenInterceptor extends Interceptor {
  async onRequest(context: InterceptorContext): Promise<void> {
    // 添加token
    context.headers['token'] = AppMode.TOKEN;
  }
}
相关推荐
M00668822 分钟前
低代码系统的技术深度:超越“可视化操作”的架构与实现挑战
android·rxjava
whysqwhw26 分钟前
Activity 的启动模式|Flags|IntentFilter
android
whysqwhw1 小时前
安卓Hook系统服务实现插件化的核心原理
android
whysqwhw1 小时前
JVM与安卓ClassLoader对比
android
深盾安全2 小时前
聊聊 Android 软件破解那些事
android
智江鹏3 小时前
Android 之 Kotlin中的符号
android·开发语言·kotlin
pengyu3 小时前
【Kotlin系统化精讲:叁】 | 变量与常量:自由与约束的代码博弈
android·kotlin
TralyFang4 小时前
Flutter CachedNetworkImage 的解码、缩放和缓存策略
flutter
勤劳打代码4 小时前
抽丝剥茧 —— 解析 PC 蓝牙检测
c++·flutter·客户端