Harmony OS Axios 的集成与封装

41 阅读4分钟

 一、引言

在 Harmony OS NEXT / 5.0 / API 12+ 版本的应用开发中,网络请求是非常关键的部分。Axios 作为一款流行的 HTTP 客户端库,能够帮助开发者轻松地处理网络请求。本文将详细介绍如何在 Harmony OS 项目中下载、导入并封装 Axios,以及在使用过程中的一些常见问题及解决方法。

二、适用版本说明

本文内容基于 Harmony OS NEXT / 5.0 / API 12+ 版本,该版本提供了良好的开发环境和 API 支持,使得 Axios 在项目中的集成与使用更加顺畅。

三、下载 Axios 包

1、下载Axios三包下面是三方仓库地址

OpenHarmony三方库中心仓https://ohpm.openharmony.cn/#/cn/home

2、如何正确导入Axios包

       2-1、进入三方库        

​编辑

        2-2、复制命令行

​编辑

        2-3、进入DevEcoStudio下载Axios(进入后我们可以快捷键 Ctrl+ ~ 打开终端拖动整个目录到终端运行 2-2 复制的命令行)        

​编辑

        2-4、进入配置文件、添加网络请求
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
    ],

​编辑

四、正确导入 Axios 包

  1. 进入三方库:就像进入 “宝库” 的特定区域寻找 Axios 这个 “宝藏”。
  2. 复制命令行:从三方库页面复制下载 Axios 所需的命令行,这相当于拿到了获取 “宝藏” 的 “钥匙”。
  3. 进入 DevEcoStudio 下载 Axios:打开 DevEcoStudio 开发环境,通过快捷键 Ctrl + ~ 打开终端,然后将整个项目目录拖动到终端,并运行刚才复制的命令行。这一步就像是用 “钥匙” 打开了存放 Axios 的 “宝箱”,将其下载到项目中。
  4. 进入配置文件、添加网络请求权限:在项目的配置文件中添加网络请求权限声明:
"requestPermissions": [
    {
        "name": "ohos.permission.INTERNET"
    }
]

这一步如同给应用颁发了一张 “网络通行证”,允许它进行网络请求操作。

五、封装 Axios 方法

封装方法一(全部)

import axios, { AxiosError, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from "@ohos/axios";
import { BASE_URL, userSetting, UserSetting } from "../../../../Index";
import settings from "@ohos.settings";
import { promptAction, router } from "@kit.ArkUI";

// 1. 创建axios的实例对象
// 配置基础地址, 超时时间
export const instance = axios.create({
    baseURL: BASE_URL,
    timeout: 100000
});

// 2. 配置请求拦截器
instance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
    const token = userSetting.getToken();
    if (token) {
        config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
}, (error: AxiosError) => {
    return Promise.reject(error);
});

// 3. 配置响应拦截器
instance.interceptors.response.use((res: AxiosResponse) => {
    // 3.1 判断业务成功
    if (res.data.code === 200) {
        return res.data;
    }
    return Promise.reject(res.data);
}, (error: AxiosError) => {
    if (error.response?.status === 401) {
        promptAction.showToast({ message: '登录失败' });
        userSetting.setToken('');
        router.pushUrl({ url: 'pages/Login/Login' });
    }
    return Promise.reject(error);
});

// 4. 封装Http类
// 提供request方法
class Http {
    request<ResponseData, RequestData = Object>(config: AxiosRequestConfig<RequestData>) {
        return instance.request<null, ResponseData, RequestData>(config);
    }
}

// 5. 创建并导出http实例对象
export const http = new Http();

  1. 导入相关模块:从 @ohos/axios 导入 axios 库以及一些类型定义,这些类型定义就像是给代码的各个部分贴上了 “标签”,让它们的作用更加明确。同时还导入了项目中的基础 URL(BASE_URL)、用户设置相关的 userSettingUserSetting,以及 @ohos.settings@kit.ArkUI 中的部分模块,为后续功能实现做准备。

  2. 创建 axios 实例:使用 axios.create 方法创建一个 axios 实例 instance,并设置了基础 URL(BASE_URL)和超时时间为 100000 毫秒(100 秒)。这就像是打造了一辆专门用于网络请求的 “汽车”,并为它设定了出发的 “基地” 和行驶的 “最长时间限制”。

  3. 配置请求拦截器:通过 instance.interceptors.request.use 配置请求拦截器,它就像一个 “关卡”,在请求发送前对请求进行检查和处理。

    • 第一个回调函数会在请求发送前执行,从 userSetting 中获取 token,如果 token 存在,就将其添加到请求头的 Authorization 字段中,为请求 “贴上身份标签”。
    • 第二个回调函数在请求发生错误时执行,以 Promise.reject 的方式抛出错误,就像告诉调用者 “这条路走不通啦,出问题了”。
  4. 配置响应拦截器:利用 instance.interceptors.response.use 配置响应拦截器,这也是一个 “关卡”,不过是在响应返回时对响应进行处理。

    • 第一个回调函数在响应成功时执行,检查响应数据的 code 字段是否为 200,如果是则返回响应数据,否则以 Promise.reject 的方式抛出响应数据,就像对 “货物” 进行检验,合格的就收下,不合格的就退回去。
    • 第二个回调函数在响应发生错误时执行,如果错误状态码为 401(表示未授权),则显示提示框告知用户 “登录失败”,清除 token 并跳转到登录页面,最后将错误以 Promise.reject 的方式抛出,这一系列操作就像是在发现 “货物” 有问题时,采取相应的措施并反馈给调用者。
  5. 封装 Http 类:定义一个 Http 类,包含一个 request 方法。这个类就像是一个 “调度中心”,统一管理网络请求。

    • request 方法是一个泛型方法,接收两个泛型参数 ResponseDataRequestData,分别表示响应数据类型和请求数据类型(默认值为 Object)。
    • 该方法调用 instance.request 方法发送请求,并返回请求的结果,就像 “调度中心” 安排 “汽车” 出发并等待它带回 “货物”。
  6. 导出 Http 实例:创建 Http 类的一个实例 http 并导出,方便在其他地方使用封装好的请求方法,就像是将 “调度中心” 的使用权开放给其他模块。

封装方法二(部分)

export class RequestAxios {
    static get<T>(url: string, params?: object): Promise<T> {
        return instance.get<null, T>(url, { params });
    }

    static post<T>(url: string, data?: object): Promise<T> {
        return instance.post<null, T>(url, data);
    }

    static delete<T>(url: string, params?: object): Promise<T> {
        return instance.delete<null, T>(url, { params });
    }

    static put<T>(url: string, data?: object): Promise<T> {
        return instance.put<null, T>(url, data);
    }
}

  1. 定义 RequestAxios 类:这个类是对 axios 实例 instance 的进一步封装,就像是给 “调度中心” 穿上了一件更便捷的 “外衣”,提供了四个静态方法,分别对应 HTTP 的四种常见请求方法:GET、POST、DELETE 和 PUT。

  2. 静态方法分析

    • GET 方法
static get<T>(url: string, params?: object): Promise<T> {
    return instance.get<null, T>(url, { params });
}

  • static 关键字表明这是一个静态方法,可以直接通过 RequestAxios.get 调用,无需创建 RequestAxios 类的实例,就像给这个方法提供了一条 “快捷通道”。
  • <T> 是泛型参数,用于指定请求响应数据的类型。调用这个方法时,能依据实际情况指定具体的响应数据类型,就像给 “货物” 贴上了一个明确的 “标签”。
  • url 参数是请求的 URL 地址,类型为字符串,告诉 “汽车” 要去哪里获取 “货物”。
  • params 参数是可选的,类型为对象,用于传递请求的查询参数,就像是给 “汽车” 带上一些 “特殊要求”。
  • instance.get<null, T>(url, { params }) 调用了之前创建的 axios 实例 instanceget 方法发起 GET 请求。null 表示请求体的数据类型,这里不需要请求体所以为 nullT 是响应数据的类型。最后返回一个 Promise,该 Promise 会在请求完成后解析为类型为 T 的响应数据,就像 “汽车” 带回了符合要求的 “货物”。
  • POST、DELETE 和 PUT 方法的原理与 GET 方法类似,只是调用的是 instance 的相应请求方法,并根据不同请求方法的特点处理参数。

六、详细分析

Http 类

  1. 功能概述Http 类主要是对 axios 实例 instance 进行了一层简单的封装,提供了一个通用的 request 方法。这个方法可以处理各种类型的 HTTP 请求,因为它接收的是一个 AxiosRequestConfig 对象,这个对象可以包含请求的所有配置信息,如请求方法、URL、参数、数据等。它就像是一个 “万能接口”,允许调用者根据具体需求来配置请求。
  2. 泛型使用request 方法使用了泛型 ResponseDataRequestData,分别表示响应数据类型和请求数据类型。调用时可以指定这两个泛型类型,以明确请求和响应的数据类型,让代码更加 “类型安全”,就像给 “货物” 和 “运输要求” 都贴上了准确的 “标签”。
  3. 灵活性与适用场景:具有较高的灵活性,因为它允许调用者完全自定义请求的配置,包括请求方法、请求头、超时时间等。但使用起来相对复杂,需要调用者对 AxiosRequestConfig 有一定的了解。适用于需要统一管理请求配置的场景,代码复用主要体现在对请求配置的统一处理上。如果项目中有很多不同类型的请求,并且需要对请求配置进行统一的修改或扩展,使用 Http 类会更合适,就像在一个大型的 “运输系统” 中,需要对各种运输任务进行统一规划和管理。

RequestAxios 类

  1. 功能概述RequestAxios 类对常见的 HTTP 请求方法(GET、POST、DELETE、PUT)进行了单独的封装,为每种请求方法提供了一个静态方法。它的目的是让调用者更方便地发起特定类型的请求,调用者只需传入必要的参数(如 URL、查询参数或请求体数据),而不需要手动配置 AxiosRequestConfig 对象,就像给调用者提供了几个 “一键操作” 的按钮,简化了请求发起的过程。
  2. 泛型使用:每个静态方法都使用了泛型 T,用于指定响应数据的类型。调用时可以根据实际情况指定 T 的具体类型,同样保证了代码的 “类型安全”。
  3. 便捷性与适用场景:更加便捷,调用者只需要关注请求的类型(GET、POST 等)、URL 和必要的参数,不需要手动配置请求方法和其他复杂的配置项。但灵活性相对较低,因为它只提供了四种常见的请求方法。适用于需要频繁发起常见 HTTP 请求的场景,代码复用主要体现在对特定请求方法的封装上。调用者可以直接使用封装好的方法,减少了重复编写请求代码的工作量,就像在一个小型的 “运输任务” 中,经常需要执行几种固定类型的运输,使用这种封装可以提高效率。

七、总结

Axios 集成三要素

1、安装命令ohpm install @ohos/axios ,这是获取 Axios “宝藏工具” 的关键指令。

2、权限声明

"requestPermissions": [{ "name": "ohos.permission.INTERNET" }]

为应用开启网络请求的 “大门”,确保能够进行网络通信。

3.、实例化配置

const instance = axios.create({
    baseURL: 'https://api.example.com',
    timeout: 10000
});

创建 axios 实例,为网络请求 “汽车” 设定 “出发基地” 和 “行驶限制”。

拦截器核心逻辑

1、请求拦截

instance.interceptors.request.use((config) => {
    config.headers.Authorization = `Bearer ${userSetting.getToken()}`;
    return config;
});

在请求发送前为其 “贴上身份标签”,确保请求的合法性。

2、 响应拦截

instance.interceptors.response.use((res) => {
    if (res.data.code!== 200) return Promise.reject(res.data);
    return res.data;
}, (error) => {
    if (error.response?.status === 401) {
        // 跳转登录页并清除 Token
    }
});

对响应 “货物” 进行检验,不合格的 “货物” 退回,并在特定错误情况下采取相应措施。

封装方案对比与选型指南

表格

场景推荐方案优势示例代码
复杂业务,需统一管理Http 类 + 拦截器灵活控制请求生命周期,支持全局日志、缓存、重试http.request<User>({ url: '/user' })
快速开发,接口标准化RequestAxios 静态方法开箱即用,减少重复代码,类型安全RequestAxios.get<User>('/user', {id:1})

常见问题

  1. 网络权限失效

    • 现象:请求报错 INTERNET permission denied。就像应用被 “拦住”,无法通过网络 “大门”。
    • 解决:检查 module.json5 权限声明,确保应用在设置中已授权网络权限。这就像是检查 “大门” 的钥匙是否正确,以及是否被允许进入。
  2. Token 未生效

    • 现象:请求头未携带 Authorization。就像 “身份标签” 没有贴好。
    • 排查:确认 userSetting.getToken() 返回值非空,拦截器逻辑未被覆盖。检查 “身份标签” 的获取和粘贴过程是否正确。
  3. 跨域问题 (CORS)

    • 现象:H5 页面调用接口报跨域错误。就像在不同 “区域” 之间通信遇到了阻碍。
    • 解决:服务端配置 Access-Control-Allow-Origin,或使用 OpenHarmony 本地代理转发。为跨域通信搭建 “桥梁”。
  4. TypeScript 类型污染

    • 现象:泛型类型 T 推断错误。就像 “标签” 贴错了。
    • 解决:明确定义接口响应类型。重新贴好正确的 “标签”。

通过本文的介绍,相信你对在 Harmony OS 中集成与封装 Axios 有了更深入的了解。关于 Harmony OS 开发中更多的技术细节和实践经验,我会在后续博客中持续分享,感兴趣的话欢迎关注。对于本文介绍的内容,你有什么疑问或者想法吗?欢迎随时交流。