直接跳到内容

网络请求

介绍

网络请求模块负责统一管理接口调用与拦截器配置,对外只暴露 DataSource。业务层通过 data 模块的 Repository 获取数据,不直接依赖网络模块。

模块结构

  • NetworkClient:统一管理 Axios 实例与基础配置。
  • interceptors:请求与响应拦截器统一注册。
  • datasource:按业务模块拆分的网络数据源接口与实现。

NetworkClient

文件位置:core/network/src/main/ets/NetworkClient.ets

拦截器

拦截器分两层:全局拦截器注册 + 日志拦截器。日志拦截器会把请求与响应打印到控制台,方便排查问题。

全局拦截器注册

文件位置:core/network/src/main/ets/interceptors/AppInterceptors.ets

登录成功后会把 Token 存到本地,后续请求会自动从本地读取并写入请求头。如需调整请求头或拦截逻辑,直接修改该文件即可。

日志拦截器

文件位置:core/network/src/main/ets/interceptors/LogInterceptor.ets

日志拦截器会把请求参数与响应结果打印到控制台,方便快速定位问题。

数据源接口与实现

下面以商品模块为例,展示 DataSource 的标准写法。

数据源接口

文件位置:core/network/src/main/ets/datasource/goods/GoodsNetworkDataSource.ets

ts
import {
  Goods, NetworkPageData, NetworkResponse, GoodsSearchRequest,
} from "model";

/**
 * @file 商品相关数据源接口
 */
export interface GoodsNetworkDataSource {
  /**
   * 分页查询商品
   * @param params 商品搜索请求参数
   * @returns 商品分页数据响应
   */
  getGoodsPage(params: GoodsSearchRequest): Promise<NetworkResponse<NetworkPageData<Goods>>>;

  /**
   * 获取商品信息
   * @param id 商品ID
   * @returns 商品信息响应
   */
  getGoodsInfo(id: string): Promise<NetworkResponse<Goods>>;
}

数据源实现

文件位置:core/network/src/main/ets/datasource/goods/GoodsNetworkDataSourceImpl.ets

ts
import { AxiosResponse } from "@ohos/axios";
import { NetworkClient } from "../../NetworkClient";
import {
  Goods, GoodsSearchRequest, NetworkPageData, NetworkResponse
} from "model";
import { GoodsNetworkDataSource } from "./GoodsNetworkDataSource";

/**
 * @file 商品相关数据源实现类
 */
export class GoodsNetworkDataSourceImpl implements GoodsNetworkDataSource {
  /**
   * 分页查询商品
   * @param params 商品搜索请求参数
   * @returns 商品分页数据响应
   */
  async getGoodsPage(params: GoodsSearchRequest): Promise<NetworkResponse<NetworkPageData<Goods>>> {
    const resp: AxiosResponse<NetworkResponse<NetworkPageData<Goods>>> =
      await NetworkClient.http.post("goods/info/page", params);
    return resp.data;
  }

  /**
   * 获取商品信息
   * @param id 商品ID
   * @returns 商品信息响应
   */
  async getGoodsInfo(id: string): Promise<NetworkResponse<Goods>> {
    const resp: AxiosResponse<NetworkResponse<Goods>> =
      await NetworkClient.http.get("goods/info/info", { params: { id } });
    return resp.data;
  }
}

仓库示例

文件位置:core/data/src/main/ets/repository/GoodsRepository.ets

ts
import { GoodsNetworkDataSource, GoodsNetworkDataSourceImpl } from "network";
import {
  Goods, GoodsSearchRequest, NetworkPageData, NetworkResponse
} from "model";

/**
 * @file 商品相关仓库类,封装商品模块请求
 */
export class GoodsRepository {
  /**
   * 商品网络数据源
   */
  private networkDataSource: GoodsNetworkDataSource;

  /**
   * 构造函数
   * @param networkDataSource 可选的商品网络数据源实例
   */
  constructor(networkDataSource?: GoodsNetworkDataSource) {
    this.networkDataSource = networkDataSource ?? new GoodsNetworkDataSourceImpl();
  }

  /**
   * 分页查询商品
   * @param params 商品搜索请求参数
   * @returns 商品分页数据
   */
  async getGoodsPage(params: GoodsSearchRequest): Promise<NetworkResponse<NetworkPageData<Goods>>> {
    return this.networkDataSource.getGoodsPage(params);
  }

  /**
   * 获取商品信息
   * @param id 商品ID
   * @returns 商品详情
   */
  async getGoodsInfo(id: string): Promise<NetworkResponse<Goods>> {
    return this.networkDataSource.getGoodsInfo(id);
  }
}

ViewModel 使用示例

文件位置:feature/demo/src/main/ets/viewmodel/NetworkRequestViewModel.ets

网络请求通常配合 result 模块的 RequestHelper 使用,用来统一处理加载状态与回调。

下面截取 GET 和 POST 的常用写法,展示如何通过仓库发起请求。

ts
import { BaseViewModel } from "base";
import { GoodsRepository } from "data";
import { Goods, GoodsSearchRequest, NetworkPageData } from "model";
import { RequestHelper } from "result";
import { ToastUtils } from "util";

/**
 * @file 通用网络请求示例页 ViewModel
 */
@ObservedV2
export default class NetworkRequestViewModel extends BaseViewModel {
  /**
   * 商品仓库
   */
  private repository: GoodsRepository = new GoodsRepository();

  /**
   * 发起 GET 请求(商品详情)
   */
  requestGoodsDetail() {
    RequestHelper.repository<Goods>(this.repository.getGoodsInfo("1"))
      .execute()
      .then((data: Goods): void => {
        // 处理 GET 请求成功逻辑
      });
  }

  /**
   * 发起 POST 请求(商品列表)
   */
  requestGoodsList() {
    const params: GoodsSearchRequest = new GoodsSearchRequest();
    params.page = 1;
    params.size = 20;
    
    RequestHelper.repository<NetworkPageData<Goods>>(this.repository.getGoodsPage(params))
      .execute()
      .then((): void => {
          // 处理 POST 请求成功逻辑
      });
  }
}

与数据层的关系

  • 网络模块不直接给业务层使用。
  • 业务通过 data 模块的 Repository 访问网络数据。
  • Repository 统一对外提供业务语义方法,保持依赖收敛。

如何新增接口

  1. core/network/src/main/ets/datasource/ 下新增业务文件夹。
  2. 编写数据源接口与实现,封装接口地址与参数。
  3. 在 data 层新增 Repository,对外提供语义化方法。
  4. 在对应 Index.ets 补充导出,保证上层统一引入。