HarmonyOS Next开发实战: 基于Axios对网络请求进行二次封装

159 篇文章 0 订阅
159 篇文章 0 订阅
一、准备工作
  • 安装好最新DevEco Studio 开发工具,创建一个新的空项目。

  • 下载安装 @ohos/axios

在项目对应模块下oh-package.json5文件 dependencies中输入"@ohos/axios": "2.2.2"

完成后参考下图点击执行 Sync Now 进行安装

  • 创建网络请求工具文件 ets/utils/request.ets
  • 创建统一管理接口文件 ets/api/index.ets
二、利用axios的create方法创建 axios 实例

这里的作用主要有下面三个:

  • 配置我们全局公共的网络请求前缀 baseURL
  • 配置统一的超时时间 timeout
  • 配置公共的统一 headers
import axios,{InternalAxiosRequestConfig, AxiosResponse,AxiosError,AxiosRequestConfig,AxiosInstance} from '@ohos/axios';
// 创建实例
const instance: AxiosInstance = axios.create({
  baseURL: 'http://XXX.XX.XX.XX', //修改为自己项目的实际地址
  timeout: 10000,//超时
  headers: { 'Content-Type': 'application/json' },
 
// `transformRequest` 允许在向服务器发送前,修改请求数据 一般来说用不到,只要后端同志是正常的
// 它只能用于 'PUT', 'POST' 和 'PATCH' 这几个请求方法
// 数组中最后一个函数必须返回一个字符串, 一个Buffer实例,ArrayBuffer,FormData,或 Stream
// 你可以修改请求头。
// transformRequest: [(data: ESObject, headers: AxiosRequestHeaders) => {
//   // 对发送的 data 进行任意转换处理
//   // console.log('api1Result出零四',data)
//   // return data
// }],

});
三、配置添加请求拦截器

这里运用最多的场景也就是把身份信息Token放入到header中携带过去传到后端。 这里还涉及到缓存信息,这个每个项目都有自己的考量,我在项目中一般用的腾讯的@tencent/mmkv,体验感还不错。

// 请求拦截器
instance.interceptors.request.use((config:InternalAxiosRequestConfig) => {
  // 对请求数据做点什么
  const  token = 'eyJhbw'//自己根据自己项目实际情况获取
  if(token){
    config.headers['token']=token //设置token
  }
  return config;
}, (error:AxiosError) => {
  // 对请求错误做些什么 
  return Promise.reject(error);
});
四、配置添加响应拦截器

下面内容用到了@ohos.router进行页面 跳转,用到了@kit.ArkUI'的promptAction.showToast 进行统一错误提示。

响应拦截非常重要,他是我们封装请求好用的关键,但是每个项目业务不同,其实响应拦截的配置都有不小的差异,但是整体思路是一致的,所以要根据自己的实际情况进行修改。

// 添加响应拦截器
instance.interceptors.response.use((response:AxiosResponse)=> {
  // 对响应数据做点什么
  // 因为 我们后台返回的 数据结构是统一的例如{code:2001,massage:'用户信息不能为空',data:{}}
  // 所以下面配置根据系统返回来配置的,不同的系统配置不同
  if(response.data.code=='2001'){ //这里是举例 要根据自己项目的实际情况进行处理
    promptAction.showToast({ //用到了 @kit.ArkUI 的 promptAction进行系统弹窗提示
      message: response.data.massage,
      duration: 2000,
      alignment:Alignment.Center
    });
    return Promise.reject(response.data);
  }
  if(response.data.code=='4001'){//这里是举例 要根据自己项目的实际情况进行处理
    router.pushUrl({ //用到了 @ohos.router 进行页面跳转
      url:"pages/LoginPage"
    })
    return Promise.reject(response.data);
  }
  return response.data;
}, (error:AxiosError)=> {
  console.log("AxiosError",JSON.stringify(error.response))
  const status = error.response?.status;
  switch (status) {
    case 401://无权限未登录
      router.pushUrl({ //用到了 @ohos.router 进行页面跳转
        url:"pages/LoginPage"
      })
      break;
    default :
      promptAction.showToast({ //用到了 @kit.ArkUI 的 promptAction进行系统弹窗提示
        message: "系统异常,请稍后再试!",
        duration: 2000,
        alignment:Alignment.Center
      });
      break
  }
  return Promise.reject(error);
});
五、使用泛型T暴露我们请求的配置

在本例中我针对后端返回的数据结构如下

{
    "code": 2001, 
    "message": "接口调用失败",
    "data": { } //data的内容不是固定的可能是null,可能是对象,也可能是数组
}

因为我们接口返回结果不固定,所以我们利用一下Ts的 泛型暴露我们封装的请求。

axios封装的完整代码如下

import axios,{InternalAxiosRequestConfig, AxiosResponse,AxiosError,AxiosRequestConfig,AxiosInstance} from '@ohos/axios';
import router from '@ohos.router';
import { promptAction } from '@kit.ArkUI';


interface ApiResponse<T> { //根据项目实际项目修改
  data: T;
  message?: string;
  code?: number;
}
// 创建实例
const instance: AxiosInstance = axios.create({
  baseURL: 'http://XXX.XXX.XXX', //修改为自己项目的实际地址
  timeout: 10000,//超时
  headers: { 'Content-Type': 'application/json' },
});

//暴露封装请求--为什么没有把上面实例放入到下面中,避免每一个接口都去创建一次
//这里利用了泛型 T 
export default <T>(config:AxiosRequestConfig): Promise<ApiResponse<T>>=> {

// 请求拦截器
instance.interceptors.request.use((config:InternalAxiosRequestConfig) => {
  // 对请求数据做点什么
  const  token = 'eyJhbGciOiJ....'//自己根据自己项目实际情况获取我大部分用的 @tencent/mmkv 插件
  if(token){
    config.headers['authorization']=token //设置token
  }
  return config;
}, (error:AxiosError) => {
  // 对请求错误做些什么
  return Promise.reject(error);
});

// 添加响应拦截器
instance.interceptors.response.use((response:AxiosResponse)=> {
  // 对响应数据做点什么
  // 因为 我们后台返回的 数据结构是统一的例如{code:2001,massage:'用户信息不能为空',data:{}}
  // 所以下面配置根据系统返回来配置的,不同的系统配置不同
  if(response.data.code=='2001'){ //这里是举例 要根据自己项目的实际情况进行处理
    promptAction.showToast({ //用到了 @kit.ArkUI 的 promptAction进行系统弹窗提示
      message: response.data.massage,
      duration: 2000,
      alignment:Alignment.Center
    });
    return Promise.reject(response.data);
  }
  if(response.data.code=='4001'){//这里是举例 要根据自己项目的实际情况进行处理
    router.pushUrl({ //用到了 @ohos.router 进行页面跳转
      url:"pages/LoginPage"
    })
    return Promise.reject(response.data);
  }
  return response.data;
}, (error:AxiosError)=> {
  console.log("AxiosError",JSON.stringify(error.response))
  const status = error.response?.status;
  switch (status) {
    case 401://无权限未登录
      router.pushUrl({ //用到了 @ohos.router 进行页面跳转
        url:"pages/LoginPage"
      })
      break;
    default :
      promptAction.showToast({ //用到了 @kit.ArkUI 的 promptAction进行系统弹窗提示
        message: "系统异常,请稍后再试!",
        duration: 2000,
        alignment:Alignment.Center
      });
      break
  }
  return Promise.reject(error);
});

return instance(config);
}
六、代码示例示范统一管理接口配置(测试)

ets/api/index.ets文件添加如下内容

import request from "../utils/request";

interface LoginParams{
  phone:string;
  code:string|number;
}


//测试登录
export function TestLogin<T>(data:LoginParams){
  return request<T>({
    url: "/test/login",
    method: "post",
    data
  });
}

//测试信息列表
export function parkList<T>(params:Record<string,string>){
  return request<T>({
    url: "/test/parks",
    method: "get",
    params
  });
}
七、代码示例示范调用(测试)

import {TestLogin } from "../api/index"
// 定义返回内容
interface ResponseLogin{
  name:string;
  code:string
}
@Entry
@Component
struct Index {

  async setTestLogin(){
    const result = await TestLogin<ResponseLogin>({phone:'13111111',code:352})
    if(result){
      console.log('result',JSON.stringify(result))
      console.log('code',JSON.stringify(result.code))
      console.log('data',JSON.stringify(result.data))
    }
  }

  build() {
    RelativeContainer() {
      Button('测试').onClick(()=>{
        this.setTestLogin();
      })
    }
    .height('100%')
    .width('100%')
  }
}
八、其他题外话

我们知道在鸿蒙开发中类型校验非常严格,而且不允许有 any 类型,如果项目赶期,声明类型是一个非常麻烦的事情。其实鸿蒙开发中也有办法,就是不要用 .ets后缀结尾。 可以 声明一个type.d.ts 文件,然后再其他.ets 文件中引入是不会报错的。

所以上面封装axios文件中 你要是嫌麻烦,也可以用下面的 类型去代替泛型T。(不建议)

//嵌套未知类型
export  interface PromiseObject {
  [key: string]: string | number |object| boolean |undefined| PromiseObject | PromiseObject[] | Array<string | number | boolean | PromiseObject |any>
}

// any 类型
export  type anyType = any;
总结

上面针对Axios的封装,基本上就能够满足大部分业务需求了,当然还有取消请求,断开重连这些我认为用到的比较少,就没有加上,如果后续掘友们觉得有必要 我可以再加上。

本篇文章写到这里就结束了,我把代码放到了gitee上

最后

小编在之前的鸿蒙系统扫盲中,有很多朋友给我留言,不同的角度的问了一些问题,我明显感觉到一点,那就是许多人参与鸿蒙开发,但是又不知道从哪里下手,因为资料太多,太杂,教授的人也多,无从选择。有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)文档用来跟着学习是非常有必要的。 

为了确保高效学习,建议规划清晰的学习路线,涵盖以下关键阶段:

 →【纯血版鸿蒙全套最新学习文档】希望这一份鸿蒙学习文档能够给大家带来帮助~


 鸿蒙(HarmonyOS NEXT)最新学习路线

该路线图包含基础技能、就业必备技能、多媒体技术、六大电商APP、进阶高级技能、实战就业级设备开发,不仅补充了华为官网未涉及的解决方案

路线图适合人群:

IT开发人员:想要拓展职业边界
零基础小白:鸿蒙爱好者,希望从0到1学习,增加一项技能。
技术提升/进阶跳槽:发展瓶颈期,提升职场竞争力,快速掌握鸿蒙技术

2.学习视频+学习PDF文档

HarmonyOS Next 最新全套视频教程 (鸿蒙语法ArkTS、TypeScript、ArkUI教程……)

​​

 纯血版鸿蒙全套学习文档(面试、文档、全套视频等)

                   

​​​​鸿蒙APP开发必备

​​

总结

【纯血版鸿蒙全套最新学习文档】

总的来说,华为鸿蒙不再兼容安卓,对程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,才能在这个变革的时代中立于不败之地。 

  • 24
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值