HarmonyOS7 HTTP 网络请求封装:统一拦截器实战

文章目录

前言

几乎每个 app 都要联网。但如果你在每个页面里都写一遍 httpRequest.request(...)、都手写错误处理、都手动拼 token,代码会又臭又长,改个 baseURL 要改二十处。

正确做法:封装一个统一的网络层。这篇文章我带你写一个带"请求拦截(自动加 token)、响应拦截(统一错误处理)"的 HTTP 封装,以后业务里一行调用就完事。

基础请求长啥样

HarmonyOS 推荐用 rcp(Remote Communication Kit)发请求,比老 http 模块更现代。

代码实现

typescript 复制代码
import { rcp } from '@kit.RemoteCommunicationKit'

async function getUsers(): Promise<User[]> {
  const session = rcp.createSession()
  const resp = await session.get('https://api.example.com/users')
  return resp.body as User[]
}

这是最原始写法,问题:没有 baseURL、没有 token、没有统一错误提示。下面我们一层层包。

第一层:统一 baseURL 和超时

typescript 复制代码
const BASE_URL = 'https://api.example.com'

class Http {
  private session: rcp.Session

  constructor() {
    this.session = rcp.createSession({
      baseAddress: BASE_URL,
      headers: { 'Content-Type': 'application/json' }
    })
  }

  async get<T>(path: string): Promise<T> {
    const resp = await this.session.get(path)
    return resp.body as T
  }
}

要点:

  • baseAddress 设一次 baseURL,后面只传 /users 这种相对路径。
  • 用泛型 <T> 让调用方拿到类型安全的返回,不用自己 cast。

第二层:请求拦截,自动带 token

真实接口基本都要登录态。与其每个请求手写 headers.token,不如在封装里统一加:

核心代码

typescript 复制代码
async get<T>(path: string): Promise<T> {
  const token = AppStorage.get<string>('token') ?? ''
  const resp = await this.session.get(path, {
    headers: { 'Authorization': 'Bearer ' + token }   // 自动注入
  })
  return this.handle(resp)   // 交给响应处理
}

AppStorage.get('token') 是全局存的登录 token,每次请求自动塞进 header。业务方完全不用管 token 从哪来。

第三层:响应拦截,统一错误处理

不同接口返回结构不同,但"成功/失败"的判断逻辑是共通的。集中处理:

完整示例

typescript 复制代码
private handle(resp: rcp.Response): any {
  const code = resp.statusCode
  if (code >= 200 && code < 300) {
    return resp.body    // 成功,返回数据
  }
  if (code === 401) {
    // token 过期,跳登录
    throw new Error('登录已过期,请重新登录')
  }
  throw new Error('请求失败:' + code)
}
  • 2xx 才视为成功,直接给业务数据。
  • 401 统一跳登录,不用每个页面判断。
  • 其他错误抛异常,调用方 try/catch 即可。

业务里怎么用

typescript 复制代码
const http = new Http()

async loadData() {
  try {
    this.users = await http.get<User[]>('/users')
  } catch (e) {
    promptAction.showToast({ message: (e as Error).message })
  }
}

业务代码干净得只剩"取数据 + 出错提示"两件事。这就是封装的价值:重复的逻辑沉到底层,业务只关心业务。

常见误区(小白必踩)

误区 说明
token 写死在业务代码里 每处手写 headers.token,改一次要改二十处。交给封装层统一注入。
不统一错误处理 每个页面自己 if (code===401),重复又易漏。集中到响应拦截里。
忘了 await 请求是异步的,不 await 拿到的是 Promise 不是数据,bug 极难查。

下面这段代码可以直接复制到 DevEco Studio 里运行。建议你边读边敲,改一改文末「动手改一改」里的参数,亲眼看看效果。

完整可运行示例:HTTP 请求封装

把 http.createHttp() 包一层,统一处理 URL、错误、返回 JSON。

代码解析

typescript 复制代码
// 一个最小可用的请求封装
import { http } from '@kit.NetworkKit'

async function getJSON<T>(url: string): Promise<T> {
  const req = http.createHttp()
  try {
    const resp = await req.request(url, { method: http.RequestMethod.GET })
    if (resp.responseCode !== 200) {
      throw new Error('HTTP ' + resp.responseCode)
    }
    return JSON.parse(resp.result as string) as T
  } finally {
    req.destroy()   // 用完释放,避免句柄泄漏
  }
}

// 使用
@Entry
@Component
struct Page {
  @State tip: string = '加载中...'
  aboutToAppear() {
    getJSON<{ title: string }>('https://example.com/api')
      .then((d) => { this.tip = d.title })
      .catch((e) => { this.tip = '出错:' + e.message })
  }
  build() { Column(){ Text(this.tip) }.padding(20) }
}

你会看到什么 :进入页面自动发请求,tip 从「加载中」变成接口返回的数据;若网络异常,tip 显示具体错误。

动手改一改:

  • 给 getJSON 增加第二个参数 body,支持 POST。
  • 在 finally 前加 console.info 打印耗时,做基础性能观测。
  • 把 tip 初始值改成空,加一个 if (this.tip) 条件渲染骨架屏。

写在最后

网络封装这套"三层结构"------baseURL、请求拦截加 token、响应拦截统错------是我每个项目的标配。它前期多花半小时,后期省下的是成倍的维护成本。

你现在就可以把项目里散落的 httpRequest 收拢到一个 Http 类里。等哪天要换域名、加签名、统一埋点,你会感谢今天做了封装的自己。

相关推荐
Lsetea10 小时前
curl访问HTTPS报47 Too many redirects:重定向循环与max-redirs排查
linux·http·https·ssl证书·curl
阿文和她的Key11 小时前
PHP2Shell事故四层拆解:AI找洞是小时级,披露协调还是邮件级
网络·人工智能·架构·php
QZ1665609515912 小时前
数据库监测的主动防御:实时感知,看见即掌控
网络·安全·网络安全
流浪00112 小时前
计算机网络篇8:传输层——序列化与反序列化,TCP 面向字节流的报文边界由应用层自己切
网络协议·tcp/ip·计算机网络·1024程序员节·序列化反序列化·面向字节流·面向数据包
贾伟康13 小时前
【健康菜谱助手|06】HarmonyOS ArkTS 烹饪计时器实战:处理倒计时、暂停、恢复和到期反馈
软件测试·移动开发·harmonyos·arkts·arkui
幻智星科技13 小时前
多通道数据采集中collect_end信号的妙用
网络协议·架构·udp·硬件架构
北京中科新远科技13 小时前
高速接口兼容排查实战:OSFP、QSFP112与QSFP56如何逐层验证
linux·运维·网络
Lzg_na15 小时前
HDLC 协议详解
网络
今天背单词了吗98015 小时前
AI 网关:大模型时代的统一接入与安全防线
网络·人工智能·安全·ai·1024程序员节
CodeGL15 小时前
13、Python基础之网络编程
网络·1024程序员节