1. 为什么要把网络请求单独设计

鸿蒙应用里的网络请求不应该散落在每个页面。页面直接创建 httpRequest、拼 URL、处理 token、解析错误,短期能跑,长期会让接口调用难以统一维护。一个成熟的网络层至少要管理基础地址、请求头、超时、错误码、重试、取消、日志和数据转换。这样页面只关心业务方法,例如 queryPatientList 或 submitReport。

2. HTTP 请求的基本链路

一次接口调用大致分成创建请求对象、配置请求参数、发送请求、解析响应、释放资源几个阶段。官方 HTTP API 提供 request 方法和 destroy 释放能力,开发时要把请求对象生命周期和页面生命周期联系起来,避免页面已经退出但请求还在回调 UI。

图 1  HTTP 请求的基本链路

3. GET 与 POST 怎么选

GET 适合查询资源,参数通常放在 URL 查询串里;POST 适合提交表单、创建记录或发送复杂 JSON。不要因为 GET 写起来方便就拿它提交敏感数据,也不要把所有查询都改成 POST。接口语义清楚后,日志、缓存、网关和测试都会更容易管理。

4. 请求头与 token 管理

请求头通常承载 Content-Type、Authorization、设备信息、语言、版本号等公共信息。token 不应该在每个页面手写拼接,而应该由统一拦截器或请求封装自动注入。token 过期时,网络层可以统一刷新或跳转登录,避免每个页面各写一套过期处理。

图 2  请求头与 token 管理

5. 响应解析要分层

接口响应通常有状态码、业务码、消息和数据体。HTTP 状态码只能说明传输层是否成功,业务码才说明业务是否成功。网络层可以先处理连接失败、超时、服务端错误,再把业务数据转换成模型对象。页面不应该直接读 result.responseCode 后猜业务含义。

6. 错误处理要分类

网络错误至少可以分为无网络、超时、服务器错误、业务错误、鉴权失败、解析失败。分类的意义是给用户不同反馈:无网络提示检查连接,超时允许重试,鉴权失败引导登录,业务错误展示服务端消息,解析失败则记录日志并兜底。

图 3  错误处理要分类

7. 请求取消和页面生命周期

列表页、搜索页、详情页都可能在请求过程中被关闭。页面退出后继续更新状态,会造成异常或脏数据。可以在页面 aboutToDisappear 或 Ability 生命周期里取消请求,也可以给 Repository 增加取消令牌。对于搜索联想,要取消上一次请求,只保留最新关键词结果。

8. 接口封装要围绕业务命名

好的接口封装不是 request('/api/user/list'),而是 queryUserList、createOrder、uploadImage。业务命名能让页面更可读,也能把 URL、方法、参数和响应模型隐藏起来。当接口地址变更时,只改数据层,不改页面。

图 4  接口封装要围绕业务命名

9. 日志和脱敏

网络日志很有用,但不能把 token、手机号、身份证、病历内容等敏感字段完整打印。开发环境可以打印详细日志,生产环境要脱敏或关闭。对于医护类应用,接口日志更要谨慎,因为患者信息属于高度敏感数据。

10. 分页和列表刷新

列表接口通常不是一次性把所有数据拉完,而是分页加载。页面要区分首次加载、下拉刷新、上拉加载更多和筛选条件变化。首次加载要展示骨架或加载状态;刷新时应重置页码;加载更多要避免重复触发;筛选条件变化时要取消旧请求并清空旧列表。把这些逻辑写在页面里会很乱,更适合封装成列表数据管理器。

11. 重试与幂等

重试并不是所有接口都能做。查询接口失败后重试通常问题不大,但创建订单、提交表单、上传护理记录这类接口如果重复发送,可能产生重复数据。后端可以提供幂等 id,前端也要在提交期间禁用按钮或记录请求状态。网络层可以统一做超时重试,但要给业务接口留下是否允许重试的配置。

12. 文件上传和进度

图片、报告、附件上传和普通 JSON 请求不同。它们更关注文件大小、上传进度、失败续传和取消。医护场景里上传护理照片或检查报告时,用户需要看到进度,也需要能在失败后重新选择或重试。文件上传完成后,数据库或页面通常只保存文件标识、URL 或业务记录,不应把大文件内容混进普通接口模型。

13. Mock 与联调

网络层封装好之后,Mock 会更简单。Repository 可以在开发阶段返回本地假数据,也可以把 HttpClient 替换成 MockClient。这样 UI 页面不必等后端接口全部完成才能开发。联调时再切换到真实客户端,并通过统一日志查看 URL、参数、响应码和业务码。

14. 医护应用的接口安全

医护类接口往往涉及患者身份、诊疗记录、护理记录和科室信息。除了 HTTPS、token、脱敏日志,还要关注接口最小权限:护士账号不应访问无关患者,普通用户不应读取后台管理接口。前端不能替代后端鉴权,但前端要避免把越权入口暴露给不相关角色。

15. 网络状态和离线兜底

真实用户不会永远处在稳定网络里。医护工作站、病区走廊、上门护理现场都可能出现弱网或临时断网。页面要区分“没有数据”和“网络失败”,不能把请求失败展示成空列表。对关键数据可以保留最近一次成功结果,并标明更新时间;对提交类操作可以保存草稿,网络恢复后提醒用户重新提交。

16. 接口文档和前端模型要同步

接口字段变化是项目里很常见的问题。后端把 patientName 改成 name,或者把状态码从数字改成字符串,页面可能不会立刻报错,却会显示异常。前端应当维护清晰的数据模型,并在 Repository 层做字段转换和默认值处理。重要接口最好配合接口文档、Mock 数据和联调用例一起维护,避免页面直接依赖后端返回的原始结构。

17. 本文小结

鸿蒙网络请求的关键不是会不会调用 http.request,而是能不能把请求做成稳定、可维护、可测试的一层。统一封装基础配置、错误处理、模型转换、分页状态、重试策略、离线兜底和生命周期管理,页面代码才会干净,线上问题也更容易定位,也更方便后续多人协作维护,减少重复返工。

16. 网络请求方案对比表

方案

适合场景

注意事项

GET

查询列表、详情、配置

避免传敏感数据,注意 URL 长度

POST

提交表单、创建资源、复杂查询

明确 Content-Type,处理重复提交

统一 HttpClient

中大型项目、多人协作

集中处理 header、token、错误和日志

17. 案例代码:封装基础 HttpClient

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

async function requestJson<T>(url: string, method: http.RequestMethod, body?: object): Promise<T> {

  const request = http.createHttp();

  try {

    const result = await request.request(url, {

      method,

      header: { 'Content-Type': 'application/json' },

      extraData: body ? JSON.stringify(body) : undefined,

      connectTimeout: 10000,

      readTimeout: 10000

    });

    return JSON.parse(result.result as string) as T;

  } finally {

    request.destroy();

  }

}

这里把创建、发送、解析和释放放在同一个函数里。页面不再直接操作 httpRequest,后续要加 token、日志、错误分类,也都可以在这里扩展。

18. 案例代码:Repository 暴露业务方法

class PatientRepository {

  async queryPatientList(keyword: string): Promise<Array<Patient>> {

    const url = `${BASE_URL}/patients?keyword=${encodeURIComponent(keyword)}`;

    const res = await requestJson<ApiResult<Array<Patient>>>(url, http.RequestMethod.GET);

    if (res.code !== 0) { throw new Error(res.message); }

    return res.data;

  }

}

Repository 用业务语言命名方法,页面只调用 queryPatientList。URL、请求方式、业务码判断和模型转换都留在数据层。

参考资料

  • HarmonyOS HTTP API 参考:https://developer.huawei.com/consumer/en/doc/harmonyos-references/js-apis-http
  • 华为开发者文档中心:https://developer.huawei.com/consumer/cn/doc/
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐