开发

ArkTS 网络请求封装:基于 NetworkKit 的 HttpEngine 实践

发布于 2026-09-08 ArkTS网络NetworkKit

几乎每个应用都绕不开网络请求。@kit.NetworkKit 提供的 http 模块功能够用但偏底层,直接在业务代码里裸调很快就会乱。这篇文章给出一套我们在真实项目中沉淀的轻量封装。

环境说明:基于 @kit.NetworkKit(API 12+,含 HarmonyOS 26),示例代码建议在 DevEco Studio 26.x 工程中验证后使用。

为什么值得封装

  • 统一配置 baseURL、超时、Header(token 注入在一处完成);
  • 统一错误处理:网络错误、HTTP 错误、业务错误码分开处理;
  • 泛型解析,业务层拿到的就是数据模型,不碰底层细节。

基础封装

import { http } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';

export interface ApiResult<T> {
  code: number;
  data: T;
  message: string;
}

export class HttpEngine {
  private static requestOptions(url: string, method: http.RequestMethod, extra?: http.HttpRequestOptions): http.HttpRequestOptions {
    return {
      method,
      url,
      connectTimeout: 10_000,
      readTimeout: 10_000,
      header: {
        'Content-Type': 'application/json',
        // TODO: 从持久化存储读取 token 注入
        // 'Authorization': `Bearer ${token}`
      },
      ...extra,
    };
  }

  static async get<T>(url: string): Promise<T> {
    return this.request<T>(url, http.RequestMethod.GET);
  }

  static async post<T>(url: string, body?: object): Promise<T> {
    return this.request<T>(url, http.RequestMethod.POST, {
      extraData: body ? JSON.stringify(body) : undefined,
    });
  }

  private static async request<T>(url: string, method: http.RequestMethod, options?: http.HttpRequestOptions): Promise<T> {
    const httpRequest = http.createHttp();
    try {
      const response = await httpRequest.request(url, this.requestOptions(url, method, options));
      if (response.responseCode !== 200) {
        throw new Error(`HTTP ${response.responseCode}`);
      }
      const result = JSON.parse(response.result as string) as ApiResult<T>;
      if (result.code !== 0) {
        throw new Error(`业务错误 [${result.code}]: ${result.message}`);
      }
      return result.data;
    } catch (err) {
      const e = err as BusinessError;
      // 这里统一转译成业务层友好的错误对象
      throw new Error(`请求失败: ${e.message ?? '未知错误'}`);
    } finally {
      httpRequest.destroy(); // 注意:destroy 不能漏,否则连接泄漏
    }
  }
}

三个容易忽略的细节

1. destroy 不能漏。 createHttp() 创建的请求对象必须 destroy(),建议在 finally 里执行。长时间运行的应用如果忘记释放,会出现连接数耗尽的问题。

2. 超时单位是毫秒。 connectTimeoutreadTimeout 都是毫秒,示例里 10_000 是 10 秒(数字分隔符是 ES2021 语法,ArkTS 支持)。

3. 错误分层。 建议分三层:网络层异常(断网、DNS 失败)、HTTP 层异常(4xx/5xx)、业务层异常(code !== 0)。UI 层的提示文案要根据层不同而区分,别把”网络断开”显示成”服务器繁忙”。

业务层调用

interface Article {
  id: number;
  title: string;
}

async load() {
  try {
    const list = await HttpEngine.get<Article[]>('https://api.example.com/articles');
    // list 已经是 Article[],直接用
  } catch (e) {
    // 统一 toast 提示
  }
}

小结

这套封装控制在 100 行以内,没有引入第三方库,适合中小型项目。如果项目复杂度上来(多域名、重试、缓存、上传进度),再考虑在封装层加拦截器链,而不是推倒重来。


相关阅读:数据能拿到了,下一步是发布——HarmonyOS 应用上架全流程


有收获的话,欢迎把本文分享给其他鸿蒙开发者。发现内容过时或有误?欢迎在评论区指出,我会持续更新。