HarmonyOS NEXT - 三方库axios的使用和封装

demo 地址: https://github.com/iotjin/JhHarmonyDemo
代码不定时更新,请前往github查看最新代码

在demo中这些组件和工具类都通过module实现了,具体可以参考HarmonyOS NEXT - 通过 module 模块化引用公共组件和utils

参考:
鸿蒙HarmonyOS开发:如何使用第三方库,加速应用开发
掌握鸿蒙网络请求:Axios网络请求库快速入门

网络请求用到的loading和本地存储

loading组件的实现看这里 HarmonyOS NEXT - Toast和Loading使用
数据持久化看这里 HarmonyOS NEXT - 数据持久化存储(key,value进行AES加密处理)

一些ohpm 命令

ohpm 官方文档

ohpm ls // 列出已安装的三方库
ohpm install @ohos/axios // 安装三方库
ohpm -v // 查询 ohpm cli 安装版本
ohpm update @ohos/axios
ohpm uninstall @ohos/axios

axios 鸿蒙库地址

安装axios

方式1:

ohpm install @ohos/axios

OpenHarmony ohpm 环境配置等更多内容,请参考如何安装 OpenHarmony ohpm 包

方式2:

直接在顶层的oh-package.json5中的dependencies 设置三方包依赖
“dependencies”: { “@ohos/axios”: “^2.2.2” },

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

点击 Sync Now同步一下

在这里插入图片描述
然后在当前目录的 oh_modules 目录下就可以看到了

在这里插入图片描述

直接使用

要请求网络数据,首先需要申请权限,需要在module.json5文件中设置网络访问权限

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

调用 axios

import axios, { AxiosError, AxiosResponse } from '@ohos/axios';
import { APIs } from './APIs';

get

    const url = APIs.apiPrefix + APIs.getPage;
    const params: object = Object({ 'page': 0, 'limit': 10 })
    axios.get(url, { params: params }).then((res: AxiosResponse) => {
      console.log("get - 返回数据:" + JSON.stringify(res.data));
      console.log(res.data['msg']);
      this.text = JSON.stringify(res.data);
    }).catch((err: AxiosError) => {
      console.log("result:" + err.message);
    });

post

    const url = APIs.apiPrefix + APIs.getSimpleDictList;
    const params: object = Object({ 'page': 0, 'limit': 10 })
    axios.post(url, params).then((res: AxiosResponse) => {
      console.log("post - 返回数据:" + JSON.stringify(res.data));
      console.log(res.data['msg']);
      this.text = JSON.stringify(res.data);
    }).catch((err: AxiosError) => {
      console.log("result:" + err.message);
    });

结果:

在这里插入图片描述

在这里插入图片描述

封装后使用

封装了2层,第一次是基础封装Request,第二次又添加了loading和返回错误弹框提示HttpUtils,这样在项目中以后只使用第二次封装的代码,如果后期需要调整会方便一点

Request

import { Request } from 'JhCommon';
import { AxiosError, AxiosResponse } from '@ohos/axios';

   const url = APIs.getPage;
   const params: object = Object({ 'page': 0, 'limit': 10 })
   Request({ url: url, method: 'get', params: params }).then((res: AxiosResponse) => {
     // res 返回的 {code,suc,msg,data}
     console.log("封装 - get - 返回数据:" + JSON.stringify(res['data']));
     console.log("msg:" + res['msg']);
   }).catch((err: AxiosError) => {
     console.log("err:" + err.message);
   });

HttpUtils

import { APIs, ErrorType, HttpUtils, ResType } from 'JhCommon';

    HttpUtils.get(url, params).then((res: ResType) => {
      console.log("二次封装 - get - 返回数据:" + JSON.stringify(res));
      console.log("二次封装 - get - 返回数据:" + JSON.stringify(res.data));
      console.log('code:', res.code)
      console.log('msg:', res.msg)
      this.text1 = JSON.stringify(res.data);
    }).catch((err: ErrorType) => {
      console.log("err:" + err.msg);
    });

    const url = APIs.apiPrefix + APIs.getSimpleDictList;
    const params: object = Object({ 'page': 0, 'limit': 10 })

    HttpUtils.post(url, params).then((res: ResType) => {
      console.log("二次封装 - post - 返回数据:" + JSON.stringify(res));
      console.log("二次封装 - post - 返回数据:" + JSON.stringify(res.data));
      console.log('code:', res.code)
      console.log('msg:', res.msg)
      this.text2 = JSON.stringify(res.data);
    }).catch((err: ErrorType) => {
      console.log("err:" + err.msg);
    });

封装代码

  • 网络请求用到的loading和本地存储:

loading组件的实现看这里 HarmonyOS NEXT - Toast和Loading使用
数据持久化看这里 HarmonyOS NEXT - 数据持久化存储(key,value进行AES加密处理)

Request.ets

///  Request.ets
///
///  Created by iotjin on 2024/08/09. 
///  description: axios工具类

import axios, { InternalAxiosRequestConfig, AxiosResponse, AxiosError } from '@ohos/axios';
import { JhProgressHUD } from '../components/JhProgressHUD';
import { JhAESPreferencesUtils } from '../utils/JhPreferencesUtils';
import { APIs } from './APIs';


// 创建 axios 实例
const service = axios.create({
  baseURL: APIs.apiPrefix,
  timeout: 50000,
  headers: { 'Content-Type': 'application/json;charset=utf-8' }
})

// default token
const defaultToken = ''
const kRefreshTokenUrl = APIs.refreshToken

function getToken() {
  const token = JhAESPreferencesUtils.getString('accessToken') ?? defaultToken
  return token
}

function setToken(accessToken: string) {
  JhAESPreferencesUtils.saveString('accessToken', accessToken)
}

function getRefreshToken() {
  const refreshToken = JhAESPreferencesUtils.getString('refreshToken') ?? ''
  return refreshToken
}

function setRefreshToken(refreshToken: string) {
  JhAESPreferencesUtils.saveString('refreshToken', refreshToken)
}

// 请求拦截器
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    const accessToken = getToken()
    if (accessToken) {
      config.headers.Authorization = 'Bearer ' + accessToken
    }
    return config
  },
  (error: AxiosError) => {
    return Promise.reject(error)
  }
)

let isRefreshing = false

// 响应拦截器
service.interceptors.response.use(
  (response: AxiosResponse) => {
    const code: number = response.data['code']
    const msg: string = response.data['msg']
    if (code === 200) {
      return response.data
    }

    // 响应数据为二进制流处理(Excel导出)
    if (response.data instanceof ArrayBuffer) {
      return response
    }

    // JhProgressHUD.showText(msg || '系统错误') // 在HttpUtils中处理
    return Promise.reject(new Error(msg || 'Error'))
  },
  async (error: AxiosError) => {
    const originalRequest: InternalAxiosRequestConfig | undefined = error.config
    // token过期
    if (error.response?.status === 401 && !isRefreshing) {
      isRefreshing = true
      try {
        // 刷新 token
        await refreshTokenRequest()
        // 刷新 Token 成功后,重新发送原始请求
        return service(originalRequest)
      } catch (refreshError) {
        return Promise.reject(refreshError)
      } finally {
        isRefreshing = false
      }
    }

    console.log('Request err: ' + JSON.stringify(error)) // for debug
    JhProgressHUD.showText(error.message || '系统错误')
    return Promise.reject(error)
  }
)

// 刷新 Token 的函数示例
async function refreshTokenRequest() {
  const params: object = Object({ 'accessToken': getToken(), 'refreshToken': getRefreshToken() })
  service({
    url: kRefreshTokenUrl,
    method: 'get',
    params: params
  }).then((res: AxiosResponse) => {
    const accessToken: string = res['data']['accessToken']
    const refreshToken: string = res['data']['accessToken']
    // 保存token
    setToken(accessToken)
    setRefreshToken(refreshToken)
  }).catch((err: AxiosError) => {
    console.log("---------- 刷新Token失败!----------" + err)
  })
}

// 导出 axios 实例
export default service

HttpUtils.ets

///  HttpUtils.ets
///
///  Created by iotjin on 2024/08/09. 
///  description: 网络请求工具类(axios二次封装)

import { AxiosError, AxiosResponse } from '@ohos/axios';
import { JhProgressHUD } from '../components/JhProgressHUD';
import Request from './Request';

// 日志开关
const isOpenLog = true

export enum Method {
  get = 'get',
  post = 'post',
  put = 'put',
  patch = 'patch',
  delete = 'delete',
  head = 'head',
}

export interface ResType {
  code: number
  msg: string
  suc: boolean
  data: ESObject
  total: number
}

export interface ErrorType {
  code: number
  msg: string
}

export class HttpUtils {
  public static get(
    url: string,
    params?: Record<string, ESObject>,
    loadingText: string = "加载中..."
  ) {
    return HttpUtils.request(Method.get, url, params, loadingText)
  }

  public static post(
    url: string,
    params?: Record<string, ESObject>,
    loadingText: string = "加载中..."
  ) {
    return HttpUtils.request(Method.post, url, params, loadingText)
  }


  public static request(
    method: Method,
    url: string,
    params?: Record<string, ESObject>,
    loadingText: string = "加载中..."
  ): Promise<ResType> {
    return new Promise<ResType>((resolve, reject) => {

      // 参数处理(如果需要加密等统一参数)
      if (isOpenLog) {
        console.log('---------- HttpUtils URL ----------')
        console.log(url)
        console.log('---------- HttpUtils params ----------')
        console.log(JSON.stringify(params))
      }

      let queryParameters: ESObject = null
      let data: ESObject = null
      if (method == Method.get) {
        queryParameters = params
      }
      if (method == Method.post) {
        data = params
      }

      if (loadingText != null && loadingText.length > 0) {
        JhProgressHUD.showLoadingText(loadingText)
      }

      Request({
        url: url,
        method: method,
        params: queryParameters,
        data: data,
      }).then((res: AxiosResponse) => {
        if (isOpenLog) {
          console.log('---------- HttpUtils response ----------')
          console.log(JSON.stringify(res))
        }
        if (loadingText != null && loadingText.length > 0) {
          JhProgressHUD.hide()
        }

        const code: number = res['code']
        const msg: string = res['msg']
        if (code === 200) {
          let result: ResType = {
            code: code,
            msg: msg,
            suc: res['suc'],
            data: res['data'],
            total: res['total'],
          }
          resolve(result)
        } else {
          JhProgressHUD.showText(msg || '系统错误')
          reject({ code: code, msg: msg })
        }
      }).catch((err: AxiosError) => {
        console.log("HttpUtils err:" + err.message)
        if (loadingText != null && loadingText.length > 0) {
          JhProgressHUD.hide()
        }
        JhProgressHUD.showText(err.message || '系统错误')
        reject({ code: err.code, msg: err.message })
      })
    })
  }
}

APIs.ets

///  APIs.ets
///
///  Created by iotjin on 2024/08/08.
///  description: api管理

export class APIs {
  /// url 前缀
  static readonly apiPrefix: string = 'https://console-mock.apipost.cn/mock/e7a66e3e-1b07-4902-9beb-366dd35ae67d/v1/api'
  /// 登录接口
  static readonly login: string = '/mock/login'
  /// 刷新token
  static readonly refreshToken: string = '/mock/refreshToken'
  /// 获取分页数据
  static readonly getPage: string = '/mock/pages'
  /// 获取分页分组数据
  static readonly getGroupPage: string = '/mock/groupPages'
  /// 获取固定数据
  static readonly getSimpleDictList: string = '/mock/simpleDictList'
  /// 获取固定数据
  static readonly getSimpleDict: string = '/mock/dict'
  /// 微信朋友圈
  static readonly getFriendsCircleList: string = '/mock/wx/moments'
}

在demo中这些组件和工具类都通过module实现了,具体可以参考HarmonyOS NEXT - 通过 module 模块化引用公共组件和utils

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西半球

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值