HarmonyOS开发5.0【封装request泛型方法】axios

一 准备工作

1. 先开启一下虚拟机的权限

src/main/module.json5 打开module.json5在15~19行 进行配置网络权限

2. 在终端下载安装一下 ohpm install @ohos/axios

复制 粘贴进去回车就行

3. 这样显示就是安装好了

如果导入不行就关了重新启动

二 创建一个ETS文件,利用静态的泛型方法对axios模块进行统一请求封装(方法名:reqeust,兼容get和post)

axios.reqeust()方法中请求参数提炼和响应泛型提炼

复制代码
import axios, { AxiosResponse, AxiosError, AxiosRequestConfig } from
 '@ohos/axios'
import { iResponseModel } from '../models/datamodel'

// 1. 准备一个axios的对象实例,同时设置好baseUrl
const req = axios.create({
  baseURL: 'https://juejin.cn/'
})

export class HdHttp {
  /*
  method:表示服务器的请求方法,Get,POST,PUT,Delete
   url:代表的是服务器的url路径(不包含基本域名地址) ,例如:user/1379256207678675
   * paramsOrData:请求传参,可选
   *
   * T:代表的是服务器响应数据中的 data这个属性的类型
   * */
  static async request<T>(method: string, url: string, paramsOrData?: object) {
    try {
      //   1. 使用req来发送请求
      let reqConfig: AxiosRequestConfig = {
        method: method,
        url: url, //是请求接口的url路径部分,并且不带有/
      }
      // 2. 分请求类型来决定传参参数是parmas还是data
      if (method == 'GET') {
        reqConfig.params = paramsOrData
      } else {
        reqConfig.data = paramsOrData
      }

      let res: AxiosResponse<iResponseModel<T>> = await req.request(reqConfig)
      //   3. 返回结果(返回的是服务器的响应报文体的数据)
      return res.data

    } catch (err) {
      //  当服务器的http状态码为非200,就会执行catch
      let errObj: AxiosError = err
      return Promise.reject(errObj.message) // 外面使用者使用try{}catch(err){}
    }
  }
}

三 增加toke携带和处理非10000的逻辑状态码的响应结果(接口响应正常,但是有逻辑异常,比如用户名或者密码错误)

复制代码
import axios, { AxiosResponse, AxiosError, AxiosRequestConfig } from '@ohos/axios'
import { iLoginUserModel, iResponseModel } from '../models/datamodel'
import { promptAction } from '@kit.ArkUI'

// 1. 准备一个axios的对象实例,同时设置好baseUrl
const req = axios.create({
  baseURL: 'https://juejin.cn/'
})

export class HdHttp {
  /*
  method:表示服务器的请求方法,Get,POST,PUT,Delete
   url:代表的是服务器的url路径(不包含基本域名地址) ,例如:user/1379256207678675
   * paramsOrData:请求传参,可选
   *
   * T:代表的是服务器响应数据中的 data这个属性的类型
   * */
  static async request<T>(method: string, url: string, paramsOrData?: object) {
    try {
      //   1. 使用req来发送请求
      let reqConfig: AxiosRequestConfig = {
        method: method,
        url: url, //是请求接口的url路径部分,并且不带有/
      }
      // 2. 分请求类型来决定传参参数是parmas还是data
      if (method == 'GET') {
        reqConfig.params = paramsOrData
      } else {
        reqConfig.data = paramsOrData
      }

      // 3. 在请求前在header中携带token
      // 获取token
      let user = AppStorage.get<iLoginUserModel>('user')
      if (user && user.token) {
        reqConfig.headers = {
          'Authorization': `Bearer ${user.token}`
        }
      }

      let res: AxiosResponse<iResponseModel<T>> = await req.request(reqConfig)

      // 4. 处理服务器响应体中的code值为非10000的情况
      if (res.data.code != 10000) {
        //  将服务器的逻辑问题信息提示给用户
        promptAction.showToast({ message: res.data.message })
        return Promise.reject(res.data.message)  //传递给外部调用者的 catch()中的信息
      }
      //   3. 返回结果(返回的是服务器的响应报文体的数据)
      return res.data

    } catch (err) {
      //  当服务器的http状态码为非200,就会执行catch
      let errObj: AxiosError = err
      return Promise.reject(errObj.message) //传递给外部调用者的 catch()中的信息 外面使用者使用try{}catch(err){}
    }
  }
}

四 在try{}catch(err){}的catch里面处理状态码为401的时跳转到登录页面,其他状态码时提示用户 errObj.response?.status == 401

复制代码
import { promptAction, router } from '@kit.ArkUI'
import axios, { AxiosResponse, AxiosError } from '@ohos/axios'
import { iLoginUserModel, iResponseModel } from '../models/datamodel'
import { HdHttp } from '../utils/request'

interface iReqBody {
  username: string
  password: string
}

@Entry
@Component
struct LoginPage {
  @State username: string = 'yu123'
  @State password: string = 'yu123456'
  @State isAgree: boolean = false
  @State islogin: boolean = false

  // 负责登录
  async login() {

    // 1. 参数合法性检查
    /*
     * ● 能对用户名和密码文本框做非空验证处理
        ● 对用户协议勾选做验证处理
      * */
    if (this.username == '' || this.password == '') {
      return promptAction.showToast({ message: '用户名和密码必填' })
    }
    if (!this.isAgree) {
      promptAction.showToast({ message: '请先勾选协议' })
      this.isAgree = true
      return
    }

    // 2. axios请求服务器接口
    this.islogin = true

    try {
      let reqBody = new Object({
        username: this.username,
        password: this.password
      })

      let res = await HdHttp.request<iLoginUserModel>('POST', 'hm/login', reqBody)
      
      this.islogin = false
      // 3. 处理服务器响应回来的报文体的数据
      //   3.1 判断服务器响应体中的code==10000的时候才保存数据,否则提示用户响应体中的message
      // if (res.data.code != 10000) {
      //   return promptAction.showToast({ message: res.data.message })
      // }

      // 3.2 将服务器响应回来的数据保存到AppStroage中,保存的数据类型是iLoginUserModel
      AppStorage.setOrCreate('user', res.data)

      // 4. 跳转到首页
      router.replaceUrl({ url: 'pages/Index' })

    } catch (err) {
      this.islogin = false
      // 将来服务器的状态码是非200的,就会自动触发catch
      let errObj: AxiosError = err //最终将err大错误对象,转为AxiosError
      AlertDialog.show({ message: errObj.message }) //最后提示给用户的是message字符串
    }
  }

  build() {
    Column() {
      // logo
      Column({ space: 10 }) {
        Image($r('app.media.icon'))
          .height(55)
          .aspectRatio(1)
      }
      .margin({ top: 170 })

      //  登录区域
      Column({ space: 20 }) {

        TextInput({ text: $$this.username })
          .backgroundColor(Color.White)
          .width('90%')
          .borderRadius(0)

        TextInput({ text: $$this.password })
          .type(InputType.Password)
          .backgroundColor(Color.White)
          .width('90%')

        Row() {
          Checkbox()
            .select(this.isAgree)
            .selectedColor('#FA6D1D')
            .onChange(value => {
              this.isAgree = value
            })

          Text('已阅读并同意')
            .fontSize(14)
            .fontColor($r('app.color.ih_gray_color'))
            .padding({ right: 4 })
          Text('用户协议')
            .fontSize(14)
            .padding({ right: 4 })
          Text('和')
            .fontSize(14)
            .fontColor($r('app.color.ih_gray_color'))
            .padding({ right: 4 })
          Text('隐私政策')
            .fontSize(14)
            .onClick(() => {
              router.pushUrl({
                url: 'pages/PreviewWebPage'
              })
            })
        }
        .width('90%')

        Button({ type: ButtonType.Normal }) {
          Row() {
            if (this.islogin) {
              LoadingProgress()
                .height(28)
                .aspectRatio(1)
                .color(Color.White)
            }
            Text('登录')
          }
        }
        .borderRadius(4)
        .width(328)
        .height(45)
        .fontColor(Color.White)
        .linearGradient({
          angle: 135,
          colors: [
            ['#FCA21C', 0],
            ['#FA6D1D', 1]
          ]
        })
        .onClick(() => {
          this.login()
        })

      }
      .margin({ top: 50 })

    }
    .width('100%')
    .height('100%')
  }
}

import axios, { AxiosResponse, AxiosError, AxiosRequestConfig } from '@ohos/axios'
import { iLoginUserModel, iResponseModel } from '../models/datamodel'
import { promptAction, router } from '@kit.ArkUI'

// 1. 准备一个axios的对象实例,同时设置好baseUrl
const req = axios.create({
  baseURL: 'https://juejin.cn/'
})

export class HdHttp {
  /*
  method:表示服务器的请求方法,Get,POST,PUT,Delete
   url:代表的是服务器的url路径(不包含基本域名地址) ,例如:user/1379256207678675
   * paramsOrData:请求传参,可选
   *
   * T:代表的是服务器响应数据中的 data这个属性的类型
   * */
  static async request<T>(method: string, url: string, paramsOrData?: object) {
    try {
      //   1. 使用req来发送请求
      let reqConfig: AxiosRequestConfig = {
        method: method,
        url: url, //是请求接口的url路径部分,并且不带有/
      }
      // 2. 分请求类型来决定传参参数是parmas还是data
      if (method == 'GET') {
        reqConfig.params = paramsOrData
      } else {
        reqConfig.data = paramsOrData
      }

      // 3. 在请求前在header中携带token
      // 获取token
      let user = AppStorage.get<iLoginUserModel>('user')
      if (user && user.token) {
        reqConfig.headers = {
          'Authorization': `Bearer ${user.token}`
        }
      }

      let res: AxiosResponse<iResponseModel<T>> = await req.request(reqConfig)

      // 4. 处理服务器响应体中的code值为非10000的情况
      if (res.data.code != 10000) {
        //  将服务器的逻辑问题信息提示给用户
        promptAction.showToast({ message: res.data.message })
        return Promise.reject(res.data.message) //传递给外部调用者的 catch()中的信息
      }
      //   3. 返回结果(返回的是服务器的响应报文体的数据)
      return res.data

    } catch (err) {
      //  当服务器的http状态码为非200,就会执行catch
      let errObj: AxiosError = err
      // 判断服务器的响应状态码如果是401,表示token失效,此时应该提示用户和跳转到登录页面
      if (errObj.response?.status == 401) {
        promptAction.showToast({ message: '登录已失效,请重新登录' })
        router.replaceUrl({ url: 'pages/LoginPage' })
      } else {
        //  提示用户是什么错误即可
        promptAction.showToast({ message: '网络异常:' + errObj.message })
      }
      // AlertDialog.show({ message: 'err:' + JSON.stringify(errObj.response?.status, null, 2) })
      return Promise.reject(errObj.message) //传递给外部调用者的 catch()中的信息 外面使用者使用try{}catch(err){}
    }
  }
}

五 提炼单独的POST < T > 和 GET< T >来简化对上一步封装好的reqeust方法的调用

封装完成 完整版

复制代码
import axios, { AxiosResponse, AxiosError, AxiosRequestConfig } from '@ohos/axios'
import { iLoginUserModel, iResponseModel } from '../models/datamodel'
import { promptAction, router } from '@kit.ArkUI'

// 1. 准备一个axios的对象实例,同时设置好baseUrl
const req = axios.create({
  baseURL: 'https://juejin.cn/'
})

export class HdHttp {
  // 这个方法给外面专门做get请求调用的
  static async Get<T>(url: string, paramsOrData?: object) {
    return await HdHttp.request<T>('GET', url, paramsOrData)
  }

  // 这个方法给外面专门做post请求调用的
  static async Post<T>(url: string, paramsOrData?: object) {
    return await HdHttp.request<T>('POST', url, paramsOrData)
  }

  /*
  method:表示服务器的请求方法,Get,POST,PUT,Delete
   url:代表的是服务器的url路径(不包含基本域名地址) ,例如:user/1379256207678675
   * paramsOrData:请求传参,可选
   *
   * T:代表的是服务器响应数据中的 data这个属性的类型
   * */
  private static async request<T>(method: string, url: string, paramsOrData?: object) {
    try {
      //   1. 使用req来发送请求
      let reqConfig: AxiosRequestConfig = {
        method: method,
        url: url, //是请求接口的url路径部分,并且不带有/
      }
      // 2. 分请求类型来决定传参参数是parmas还是data
      if (method == 'GET') {
        reqConfig.params = paramsOrData
      } else {
        reqConfig.data = paramsOrData
      }

      // 3. 在请求前在header中携带token
      // 获取token
      let user = AppStorage.get<iLoginUserModel>('user')
      if (user && user.token) {
        reqConfig.headers = {
          'Authorization': `Bearer ${user.token}`
        }
      }

      let res: AxiosResponse<iResponseModel<T>> = await req.request(reqConfig)

      // 4. 处理服务器响应体中的code值为非10000的情况
      if (res.data.code != 10000) {
        //  将服务器的逻辑问题信息提示给用户
        promptAction.showToast({ message: res.data.message })
        return Promise.reject(res.data.message) //传递给外部调用者的 catch()中的信息
      }
      //   3. 返回结果(返回的是服务器的响应报文体的数据)
      return res.data

    } catch (err) {
      //  当服务器的http状态码为非200,就会执行catch
      let errObj: AxiosError = err
      // 判断服务器的响应状态码如果是401,表示token失效,此时应该提示用户和跳转到登录页面
      if (errObj.response?.status == 401) {
        promptAction.showToast({ message: '登录已失效,请重新登录' })
        router.replaceUrl({ url: 'pages/LoginPage' })
      } else {
        //  提示用户是什么错误即可
        promptAction.showToast({ message: '网络异常:' + errObj.message })
      }
      // AlertDialog.show({ message: 'err:' + JSON.stringify(errObj.response?.status, null, 2) })
      return Promise.reject(errObj.message) //传递给外部调用者的 catch()中的信息 外面使用者使用try{}catch(err){}
    }
  }
}

总结

以上是我在项目中的用到的关于 axios 的一些封装方法。

以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!

下面是鸿蒙的完整学习路线 ,展示如下:

除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下

内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

鸿蒙【北向应用开发+南向系统层开发】文档

鸿蒙【基础+实战项目】视频

鸿蒙面经

为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!

相关推荐
qq_5537603237 分钟前
Harmony OS:全模态对话框(广告)与文本切换功能实现
harmonyos·鸿蒙
搞瓶可乐2 小时前
【HarmonyOS开发】鸿蒙应用开发发展史:从技术探索到生态爆发,一文读懂其演进脉络
harmonyos·arkts
互联网散修2 小时前
鸿蒙(HarmonyOS)ArkTS 实战: animateTo属性动画实现连续涟漪扩散
华为·harmonyos·鸿蒙属性动画
钱塘江渔夫5 小时前
一键搭建OpenHarmony arkcompiler开发环境
openharmony·arkcompiler
lxysbly6 小时前
鸿蒙harmonyos端怀旧游戏模拟器,支持fc红白机 街机 gba psp ps1 nds n64世嘉md gbc gb sfc等主机
游戏·华为·harmonyos
ShuiShenHuoLe7 小时前
02Navigation页面路由
harmonyos·鸿蒙
飞凌嵌入式7 小时前
飞凌嵌入式RK3506J核心板通过OpenHarmony 5.1兼容性认证
嵌入式硬件·开源·鸿蒙
想你依然心痛7 小时前
HarmonyOS 5.0行业解决方案:基于端侧AI的智能工业质检APP开发实战
人工智能·华为·harmonyos
Sylus_sui8 小时前
鸿蒙 HarmonyOS 4.0+ 音乐播放器企业级完整实现(后台播放 + 系统播控中心 + 全功能)
华为·harmonyos
轻口味9 小时前
HarmonyOS 6 原生高性能相机框架:GPUImage (libgpuimagelib) 深度架构解析与实战全纪录
数码相机·架构·harmonyos