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内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

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

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

鸿蒙面经

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

相关推荐
ClkLog-开源埋点用户分析11 分钟前
ClkLog企业版(CDP)预售开启,更有鸿蒙SDK前来助力
华为·开源·开源软件·harmonyos
mg66814 分钟前
鸿蒙系统的优势 开发 环境搭建 开发小示例
华为·harmonyos
lqj_本人41 分钟前
鸿蒙next选择 Flutter 开发跨平台应用的原因
flutter·华为·harmonyos
lqj_本人44 分钟前
使用 Flutter 绘制一个棋盘
harmonyos
lqj_本人4 小时前
Flutter&鸿蒙next 状态管理框架对比分析
flutter·华为·harmonyos
青瓷看世界5 小时前
华为HarmonyOS打造开放、合规的广告生态 - 插屏广告
华为·harmonyos·广告投放
青瓷看世界5 小时前
华为HarmonyOS借助AR引擎帮助应用实现虚拟与现实交互的能力2-管理AR会话
华为·ar·harmonyos·虚拟现实
2301_795558646 小时前
鸿蒙的进化史
华为·harmonyos
Swift社区6 小时前
HarmonyOS App 购物助手工具的开发与设计
harmonyos·arkts·arkui
前端李易安6 小时前
手写一个axios方法
前端·vue.js·axios