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

news2024/11/15 22:45:23

一 准备工作

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

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

1

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

复制 粘贴进去回车就行

2

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

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

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 的一些封装方法。

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

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

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

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

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

鸿蒙面经

2

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2126924.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

后端开发刷题 | 矩阵的最小路径和

描述 给定一个 n * m 的矩阵 a&#xff0c;从左上角开始每次只能向右或者向下走&#xff0c;最后到达右下角的位置&#xff0c;路径上所有的数字累加起来就是路径和&#xff0c;输出所有的路径中最小的路径和。 数据范围: 1≤n,m≤500&#xff0c;矩阵中任意值都满足 0≤ai,j…

Linux系统:cd命令

1、命令详解&#xff1a; cd命令用于改变当前工作目录的命令&#xff0c;切换到指定的路径&#xff0c;全称为change directory&#xff0c;若目录名称省略&#xff0c;则默认变换至使用者的 home 目录。 2、官方参数&#xff1a; 选项&#xff1a;-L 强制遵循符号链接-P 使用…

基于RFID技术的光交箱哑资源智能化管理方案

一、现状 &#xff08;一&#xff09;现状与挑战 在当前通信网络基础设施中&#xff0c;哑资源如光缆接头、跳线等在网络中占据着重要地位。然而&#xff0c;传统的哑资源管理方式存在诸多问题&#xff0c;一方面&#xff0c;管理主要依赖人工记录和定期巡检&#xff0c;效率…

每日OJ_牛客_合唱团(打家劫舍dp)

目录 牛客_合唱团&#xff08;打家劫舍dp&#xff09; 解析代码1 解析代码2 牛客_合唱团&#xff08;打家劫舍dp&#xff09; 合唱团__牛客网 有 n 个学生站成一排&#xff0c;每个学生有一个能力值&#xff0c;牛牛想从这 n 个学生中按照顺序选取 k 名学生&#xff0c;要求…

MongoDB高可用和分片集群知识

一、MongoDB实现高可用 1. MongoDB复制集(Replication Set) 在实际生产中&#xff0c;MongoDB要实现高可用&#xff0c;以免MongoDB单实例挂了&#xff0c;服务不可用。MongoDB实现高可用是以MongoDB复制集的形式实现&#xff0c;和集群部署概念相同&#xff0c;MongoDB复制集…

火柴人跑酷

运行图片&#xff1a; 这里面有三个boss&#xff0c;和各种元素属性列举一下&#xff1a; 元素作用 火 运用火元素将攻击抵消 水 和火元素一致 磁 自动吸取经验…

vscode设置vue标签不换行

1、打开 文件 --> 首选项 --> 设置 2、在设置里搜索 vetur.format&#xff0c;项较多&#xff0c;向下滑动找到 在 setting.json 中编辑 按钮 点进去 3、修改配置文件vetur.format.defaultFormatterOptions {"files.autoSave": "afterDelay","…

全网最适合入门的面向对象编程教程:47 Python函数方法与接口-回调函数Callback

全网最适合入门的面向对象编程教程&#xff1a;47 Python 函数方法与接口-回调函数 Callback 摘要&#xff1a; 回调函数是编程中一种非常常见的模式&#xff0c;用于将函数作为参数传递给其他函数或方法。这种模式在 Python 中广泛应用于事件处理、异步编程、函数式编程等场景…

cadence SPB17.4 - ORCAD - ERROR(ORCAP-1616): Reference is invalid for this part

文章目录 cadence SPB17.4 - ORCAD - ERROR(ORCAP-1616): Reference is invalid for this part概述笔记END cadence SPB17.4 - ORCAD - ERROR(ORCAP-1616): Reference is invalid for this part 概述 在抄GDLink on Board的原理图。 抄完之后进行原理图DRC, 有个元件报错。 …

C语言代码练习(第十八天)

今日练习&#xff1a; 48、猴子吃桃问题。猴子第1天摘下若干个桃子&#xff0c;当即吃了一半&#xff0c;还不过瘾&#xff0c;又多吃了一个。第2天早上又将剩下的桃子吃掉一半&#xff0c;又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时&…

digits Social Login插件 google OAuth 2.0登录 400 redirect_uri_mismatch错误解决

以下是Social Login插件google登录配置&#xff1a; 直接使用这个URI 会在登录时提示错误&#xff1a;400 redirect_uri_mismatch&#xff0c;此时需要点击错误详情把这个重定向URI设置到google中即可

Java:类和对象(2)

一 对象的构建和初始化 1.对象构建 (Object Construction) Student student1new Student("zhangsan",12,"123456"); Student student2new Student("lisi",10,"15236"); 2. 构造函数&#xff08;Constructor&#xff09; 构造函数的…

Android binder 机制驱动核心源码详解_binder_thread_read

binder 驱动中做的工作可以总结为以下几步&#xff1a; 准备数据&#xff0c;根据命令分发给具体的方法去处理找到目标进程的相关信息将数据一次拷贝到目标进程所映射的物理内存块记录待处理的任务&#xff0c;唤醒目标线程调用线程进入休眠目标进程直接拿到数据进行处理&…

maven安装依赖

这里以安装tomcat依赖为例 1, 访问maven公共仓库 2,搜索tomcat 3, 右侧点击Plugin 选择&#xff1a;Apache Tomcat Maven Plugin :: Tomcat 7.x 选择版本&#xff0c;这里我选择2.2 选择maven&#xff0c;将<dependency>中的内容copy到pom.xml中的<build>里面 …

webctf

熟悉robots.txt协议&#xff0c;可能存在一些敏感信息(sql在登录时候的万能密码a’ or true#)熟悉phps文件&#xff0c;phps文件就是 php 的源代码文件&#xff0c;通常用于提供给用户&#xff08;访问者&#xff09;查看 php 代码&#xff0c;因为用户无法直接通过 Web 浏览器…

力扣279-完全平方数(Java详细题解)

题目链接&#xff1a;279. 完全平方数 - 力扣&#xff08;LeetCode&#xff09; 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 最近刚学完背包&#xff0c;所以现在的题解都是以背包问题为基础再来写的。 如果大家不懂背包问题的话&…

测试阶段例题

答案&#xff1a;D 测试阶段划分 单元测试 模块测试&#xff0c;模块功能&#xff0c;性能&#xff0c;接口等 集成测试 模块间的接口 系统测试 真实环境下&#xff0c;验证完整的软件配置能否和系统正确连接 确认测试 验证软件与需求的一致性。内部确认测试&#xff0…

k8s独立组件ingress,七层转发

一、K8S的Service 1、Service的作用 Service的作用体现在两个方面&#xff1a; 1、集群内部&#xff1a;不断跟踪pod的变化&#xff0c;更新endpoints中的pod对象&#xff0c;基于pod的IP地址不断变化的一种服务发现机制&#xff0c;也可以实现负载均衡&#xff0c;四层代理…

vue element时间选择不能超过今天 时间选中长度不能超过7天

背景&#xff1a; 使用elenmet plus 组件实现时间选择&#xff1b;且日期时间选择不能超过今天&#xff1b;连续选中时间的长度范围不能超过7天 效果展示&#xff1a; 实现思路&#xff1a; 一、使用element组件自带的属性和方法&#xff1b; :disabled-date"disabledDate…

misc音频隐写

一、MP3隐写 &#xff08;1&#xff09;题解&#xff1a;下载附件之后是一个mp3的音频文件&#xff1b;并且题目提示keysyclovergeek;所以直接使用MP3stego对音频文件进行解密&#xff1b;mp3stego工具是音频数据分析与隐写工具 &#xff08;2)mp3stego工具的使用&#xff1a;…