• 作者:老汪软件技巧
  • 发表时间:2024-11-11 15:03
  • 浏览量:

一、引言

鸿蒙操作系统HarmonyOS作为新兴的跨设备平台,为开发者提供了广阔的创新空间。然而,由于其相对较新,许多开发者可能对其技术细节尚不熟悉,特别是在网络请求处理方面。axios作为一个成熟的HTTP客户端库,其强大的功能和灵活的配置使其成为处理网络请求的首选工具。在此,我也同样是初学者,我们共同学习,如有任何不足之处,敬请各位不吝赐教。

鸿蒙操作系统(OpenHarmony)的开发涉及到特定的工具和依赖管理。以下是在鸿蒙系统中封装和使用axios的一些步骤和命令,以及如何使用ohpm(OpenHarmony Package Manager)来管理依赖。

ohpm常用命令

ohpm官方文档

ohpm ls // 列出已安装的三方库
ohpm install  // 安装三方库
ohpm -v // 查询 ohpm cli 安装版本
ohpm update   更新依赖
ohpm uninstall   卸载依赖
ohpm publish  发布包

安装@ohos/axios

ohos/axios是适用于鸿蒙系统的axios封装,你可以使用以下命令来安装它:

ohpm install @ohos/axios

Snipaste_2024-11-10_22-29-18.png

安装完成后在 oh-package.json5 文件中的 dependencies 可以看到是否安装该依赖

{
  "modelVersion": "5.0.0",
  "description": "Please describe the basic information.",
  "dependencies": {
    "@ohos/axios": "^2.2.4"
  },
  "devDependencies": {
    "@ohos/hypium": "1.0.19",
    "@ohos/hamock": "1.0.0"
  },
  "dynamicDependencies": {}
}

156.png

请求网络数据,首先需要申请权限,你需要在module.json5文件中申请网络访问权限。如下图所示。

Snipaste_2024-11-10_23-12-28.png

二、封装步骤

接下来则是封装 axios:在你的项目中创建一个文件 文件名自定义

1. 导入依赖

导入所需的模块

import axios, { InternalAxiosRequestConfig, AxiosResponse, AxiosError, AxiosInstance } from '@ohos/axios';
import { promptAction } from '@kit.ArkUI';
import { checkStatus } from './helper/checkStatus';
import { logger } from '../utils/Logger';

2. 定义响应数据结构

根据项目需求 以下为示例,定义ApiResponse接口:

interface ApiResponse { //根据项目实际项目修改
  code?: number;
  data: T | null;
  message?: string;
}

詹红荔精神的实践与探讨__网络请求封装及调用vue

3. 创建axios实例

创建一个axios实例,并配置基础信息:

// 创建实例
const instance: AxiosInstance = axios.create({
  // 默认地址请求地址
  baseURL: 'http://localhost:8617/', //修改为自己项目的实际地址
  // 设置超时时间
  timeout: 100000,
  headers: {
    'Content-Type': 'application/json;charset=utf-8',
    'Content-Language': 'zh_CN'
  },
});

4. 添加请求拦截器

在请求拦截器中,可以统一处理请求头、请求参数等:

// 添加请求拦截器
instance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
  // 对请求数据做点什么
  const token = 'token....'
  if (token) {
    config.headers['Authorization'] = 'Bearer ' + token //设置token
  }
  return config
}, (error: AxiosError) => {
  // 对请求错误做些什么
  return Promise.reject(error)
})

5. 添加响应拦截器

在响应拦截器中,可以统一处理响应数据、错误提示等:checkStatus文件在后面展示补充

// 添加响应拦截器 错误统一处理等
instance.interceptors.response.use((response: AxiosResponse) => {
  // 对响应数据做点什么
  // 下面配置根据系统返回来配置的,不同的系统配置不同
  if (response.data.code == 200) { // 这里是举例 要根据自己项目的实际情况进行处理
    promptAction.showToast({
      //用到了 @kit.ArkUI 的 promptAction进行系统弹窗提示
      message: response.data.massage,
      duration: 2000,
      alignment: Alignment.Center
    });
    logger.debug("请求成功", JSON.stringify(response))
    return Promise.reject(response.data);
  } else {
    // 根据不同的错误码进行不同的处理
    // promptAction.showToast({
    //   message: response.data.message || '请求失败,请稍后重试',
    //   duration: 2000,
    //   alignment: Alignment.Center
    // });
    logger.error("Error", JSON.stringify(response))
    // return Promise.reject(response);
  }
  return response
}, (error: AxiosError) => {
  // 请求超时 && 网络错误单独判断,没有 response
  if (error.message.indexOf("timeout") !== -1) {
    promptAction.showToast({ message: "请求超时!请您稍后重试" });
  }
  if (error.message.indexOf("Network Error") !== -1) {
    promptAction.showToast({ message: "网络错误!请您稍后重试" });
  }
  console.log("AxiosError", JSON.stringify(error.response))
  // 根据服务器响应的错误状态码,做不同的处理
  const status = error.response?.status;
  console.log('status', status)
  if (status) {
    checkStatus(status);
  }
  logger.error("error", JSON.stringify(error))
  return Promise.reject(error)
})

6. 补充引入的文件 checkStatus 和 logger

// Logger.ets
import { hilog } from '@kit.PerformanceAnalysisKit';
const LOGGER_PREFIX: string = 'interview_success_logger';
class Logger {
  private domain: number;
  private prefix: string;
  private format: string = '%{public}s, %{public}s';
  constructor(prefix: string = '', domain: number = 0x0000) {
    this.prefix = prefix;
    this.domain = domain;
  }
  debug(...args: string[]): void {
    hilog.debug(this.domain, this.prefix, this.format, args);
  }
  info(...args: string[]): void {
    hilog.info(this.domain, this.prefix, this.format, args);
  }
  warn(...args: string[]): void {
    hilog.warn(this.domain, this.prefix, this.format, args);
  }
  error(...args: string[]): void {
    hilog.error(this.domain, this.prefix, this.format, args);
  }
}
export const logger =  new Logger(LOGGER_PREFIX, 0x1234);

// checkStatus.ets
import { promptAction } from '@kit.ArkUI';
/**
 * @description: 校验网络请求状态码
 * @param {Number} status
 * @return void
 */
export const checkStatus = (status: number) => {
  switch (status) {
    case 400:
      promptAction.showToast({ message: "请求失败!请您稍后重试" })
      break;
    case 401:
      promptAction.showToast({ message: "登录失效!请您重新登录" })
      break;
    case 403:
      promptAction.showToast({ message: "当前账号无权限访问!" })
      break;
    case 404:
      promptAction.showToast({ message: "你所访问的资源不存在!" })
      break;
    case 405:
      promptAction.showToast({ message: "请求方式错误!请您稍后重试" })
      break;
    case 408:
      promptAction.showToast({ message: "请求超时!请您稍后重试" })
      break;
    case 500:
      promptAction.showToast({ message: "服务异常!" })
      break;
    case 502:
      promptAction.showToast({ message: "网关错误!" })
      break;
    case 503:
      promptAction.showToast({ message: "服务不可用!" })
      break;
    case 504:
      promptAction.showToast({ message: "网关超时!" })
      break;
    default:
      promptAction.showToast({ message: "请求失败!" })
  }
};

6. 封装请求方法

创建一个RequestHttp类,封装get、post、delete、put等方法:

// 封装请求方法
class RequestHttp {
  get(url: string, params?: object): Promise<ApiResponse> {
    return instance.get<null, ApiResponse>(url, { params })
  }
  // 封装post方法
  post(url: string, data?: object): Promise<ApiResponse> {
    return instance.post<null, ApiResponse>(url, data)
  }
  // 封装delete方法
  delete(url: string, data?: object): Promise<ApiResponse> {
    return instance.delete<null, ApiResponse>(url, data)
  }
  // 封装put方法
  put(url: string, data?: object): Promise<ApiResponse> {
    return instance.put<null, ApiResponse>(url, data)
  }
}
export const http = new RequestHttp();

以上则是对axios的基础封装,根据项目需要可以自行对其修改,例如添加上传、下载文件的方法,支持取消请求等。

7. 代码示例示范调用

定义接口文件

import { http } from "../api/index";
interface CardNoParams{
  name:string;
  cardNo:string|number;
}
interface ApiResponse { //根据项目实际项目修改
  code?: number;
  data: object | null;
  message?: string;
}
// 根据姓名身份证查询
export function viewByNameAndCardNo(data:CardNoParams){
  return http.post<ApiResponse>("/yjzgbtyj/viewCardNo", data)
}


import { viewByNameAndCardNo } from '../../api/serviceGuide'
dialogController: CustomDialogController = new CustomDialogController({
  builder: CustomContentDialog({
    primaryTitle: '请输入信息', // 弹出框标题
    secondaryTitle: '', // 弹出框辅助文本
    contentBuilder: () => {
      this.buildContent();
    },
    buttons: [
      {
        value: '确定',
        buttonStyle: ButtonStyleMode.TEXTUAL,
        action: async () => {
          if (!this.cardNo || !this.name) {
            return promptAction.showToast({ message: "请输入完整的身份证号码和姓名" })
          }
          const res = await viewByNameAndCardNo({name: this.name, cardNo: this.cardNo})
          console.log('res',JSON.stringify(res))
          if (res.code === 200) {
            console.log('result',JSON.stringify(res))
          }else{
            console.log('请求失败',JSON.stringify(res))
            promptAction.showToast({ message: "查询不到该用户信息,请核对后重新输入!" })
          }
        }
      },
      {
        value: '取消',
        buttonStyle: ButtonStyleMode.TEXTUAL, role: ButtonRole.ERROR
      }
    ],
  }),
  alignment: DialogAlignment.Center,
  cornerRadius: 10,
});

五、总结

本文详细介绍了在鸿蒙系统中使用axios进行网络请求的封装与优化。通过封装,我们可以提高代码的可维护性、可读性,降低开发成本。在实际项目中,开发者可以根据具体需求进行相应的调整和优化。希望本文对您在鸿蒙系统开发过程中有所帮助。