HarmonyOS 鸿蒙应用开发 (七、HTTP网络组件 axios 介绍及封装使用)

需要配置 ohos.permission.INTERNET权限。在工程目录entry\src\main中找到module.json5文件,配置网络请求权限。

{

“module”: {

“name”: “entry”,

“type”: “entry”,

“description”: “$string:module_desc”,

“mainElement”: “EntryAbility”,

“deviceTypes”: [

“phone”

],

“requestPermissions”: [

{

“name”: “ohos.permission.INTERNET”

}

]

}

}

简单使用

import axios from ‘@ohos/axios’

//创建axios的实例

const instance = axios.create({

baseURL: “http://xx.xx.xx.xx”, //基路径,要看API帮助文档的特征来确定基路径

timeout: 5000, //请求超时的时间

headers: {

“Content-Type”: “application/json”

}

})

//响应拦截器,通过响应拦截器进一步对返回的数据做处理

instance.interceptors.response.use((response) => {

//只返回接口有数据的结果

if (200 === response.status) {

return response.data; //接口返回的数据

}

return Promise.reject(response); //表示请求有错,交给catch来处理结构

}, err => {

return Promise.reject(err)

})

/**

  • get请求
  • @param params = {} 查询参数
  • @returns

    */

    export function httpGet(url:string, params = {}) {

    return instance.get(url, {

    params

    })

    }

    /**

    • post请求
    • @param data = {} 请求体数据
    • @returns

      */

      export function httpPost(url:string, data = {}) {

      return instance.post(url, {

      data

      })

      }

      axios模块封装及使用

      axios模块封装:

      //AxiosHttp.ets

      import axios, {

      AxiosInstance,

      AxiosRequestConfig,

      AxiosRequestHeaders,

      AxiosResponse,

      InternalAxiosRequestConfig

      } from “@ohos/axios”;

      import { LogUtils } from ‘…/utils/LogUtils’;

      /**

      • 定义接口响应包装类

        */

        export interface BaseResponse {

        //wanAndroid-API响应体

        errorCode: number

        errorMsg: string

        //拓展xxx-API响应体

        }

        /**

        • 接口实现类包装,例如有其他业务可以再次继承实现xxxResponse

          */

          export interface ApiResponse extends BaseResponse {

          //wanAndroid-API响应体

          data: T | any;

          //拓展xxx-API响应体

          }

          /**

          • 封装后,不支持传入拦截器
          • 需要自己定义接口继承 AxiosRequestConfig类型
          • 从而支持传入拦截器,但拦截器选项应为可选属性
          • 之后请求实例传入的options为继承了AxiosRequestConfig的自定义类型

            */

            interface InterceptorHooks {

            requestInterceptor?: (config: HttpRequestConfig) => Promise;

            requestInterceptorCatch?: (error: any) => any;

            responseInterceptor?: (response: AxiosResponse) => AxiosResponse | Promise;

            responseInterceptorCatch?: (error: any) => any;

            }

            // @ts-ignore

            interface HttpRequestConfig extends InternalAxiosRequestConfig {

            showLoading?: boolean; //是否展示请求loading

            checkResultCode?: boolean; //是否检验响应结果码

            checkLoginState?: boolean //校验用户登陆状态

            needJumpToLogin?: boolean //是否需要跳转到登陆页面

            interceptorHooks?: InterceptorHooks;

            headers?: AxiosRequestHeaders

            }

            /**

            • 网络请求构造
            • 基于axios框架实现

              */

              class AxiosHttpRequest {

              config: HttpRequestConfig;

              interceptorHooks?: InterceptorHooks;

              instance: AxiosInstance;

              constructor(options: HttpRequestConfig) {

              this.config = options;

              this.interceptorHooks = options.interceptorHooks;

              this.instance = axios.create(options);

              this.setupInterceptor()

              }

              setupInterceptor(): void {

              this.instance.interceptors.request.use(

              //这里主要是高版本的axios中设置拦截器的时候里面的Config属性必须是InternalAxiosRequestConfig,但是InternalAxiosRequestConfig里面的headers是必传,所以在实现的子类我设置成非必传会报错,加了个忽略注解

              // @ts-ignore

              this.interceptorHooks?.requestInterceptor,

              this.interceptorHooks?.requestInterceptorCatch,

              );

              this.instance.interceptors.response.use(

              this.interceptorHooks?.responseInterceptor,

              this.interceptorHooks?.responseInterceptorCatch,

              );

              }

              // 类型参数的作用,T决定AxiosResponse实例中data的类型

              request(config: HttpRequestConfig): Promise {

              return new Promise((resolve, reject) => {

              this.instance

              .request(config)

              .then(res => {

              resolve(res);

              })

              .catch((err) => {

              LogUtils.error(“网络请求Request异常:”, err.message)

              errorHandler(err)

              if (err) {

              reject(err);

              }

              });

              });

              }

              get(config: HttpRequestConfig): Promise {

              return this.request({ …config, method: ‘GET’ });

              }

              post(config: HttpRequestConfig): Promise {

              return this.request({ …config, method: ‘POST’ });

              }

              delete(config: HttpRequestConfig): Promise {

              return this.request({ …config, method: ‘DELETE’ });

              }

              patch(config: HttpRequestConfig): Promise {

              return this.request({ …config, method: ‘PATCH’ });

              }

              }

              export function errorHandler(error: any) {

              if (error instanceof AxiosError) {

              showToast(error.message)

              } else if (error != undefined && error.response != undefined && error.response.status) {

              switch (error.response.status) {

              // 401: 未登录

              // 未登录则跳转登录页面,并携带当前页面的路径

              // 在登录成功后返回当前页面,这一步需要在登录页操作。

              case 401:

              break;

              // 403 token过期

              // 登录过期对用户进行提示

              // 清除本地token和清空vuex中token对象

              // 跳转登录页面

              case 403:

              showToast(“登录过期,请重新登录”)

              // 清除token

              // localStorage.removeItem(‘token’);

              break;

              // 404请求不存在

              case 404:

              showToast(“网络请求不存在”)

              break;

              // 其他错误,直接抛出错误提示

              default:

              showToast(error.response.data.message)

              }

              }

              }

              export default AxiosHttpRequest

              客户端封装

              //AxiosRequest.ets

              import {AxiosHttpRequest,errorHandler} from ‘./AxiosHttp’

              import { AxiosError, AxiosRequestHeaders } from ‘@ohos/axios’;

              import { LogUtils } from ‘…/utils/LogUtils’;

              import showToast from ‘…/utils/ToastUtils’;

              import { hideLoadingDialog, showLoadingDialog } from ‘…/utils/DialogUtils’;

              import { StorageUtils } from ‘…/utils/StorageUtils’;

              import { StorageKeys } from ‘…/constants/StorageKeys’;

              import { JsonUtils } from ‘…/utils/JsonUtils’;

              import { Router } from ‘…/route/Router’;

              import { RoutePath } from ‘…/route/RoutePath’;

              /**

              • axios请求客户端创建

                */

                const axiosClient = new AxiosHttpRequest({

                baseURL: “/api”,

                timeout: 10 * 1000,

                checkResultCode: false,

                headers: {

                ‘Content-Type’: ‘application/json’

                } as AxiosRequestHeaders,

                interceptorHooks: {

                requestInterceptor: async (config) => {

                // 在发送请求之前做一些处理,例如打印请求信息

                LogUtils.debug(‘网络请求Request 请求方法:’, ${config.method});

                LogUtils.debug(‘网络请求Request 请求链接:’, ${config.url});

                LogUtils.debug(‘网络请求Request Params:’, \n${JsonUtils.stringify(config.params)});

                LogUtils.debug(‘网络请求Request Data:’, ${JsonUtils.stringify(config.data)});

                axiosClient.config.showLoading = config.showLoading

                if (config.showLoading) {

                showLoadingDialog(“加载中…”)

                }

                if (config.checkLoginState) {

                let hasLogin = await StorageUtils.get(StorageKeys.USER_LOGIN, false)

                LogUtils.debug(‘网络请求Request 登录状态校验>>>’, ${hasLogin.toString()});

                if (hasLogin) {

                return config

                } else {

                if (config.needJumpToLogin) {

                Router.push(RoutePath.TestPage)

                }

                throw new AxiosError(“请登录”)

                }

                }

                return config;

                },

                requestInterceptorCatch: (err) => {

                LogUtils.error(“网络请求RequestError”, err.toString())

                if (axiosClient.config.showLoading) {

                hideLoadingDialog()

                }

                return err;

                },

                responseInterceptor: (response) => {

                //优先执行自己的请求响应拦截器,在执行通用请求request的

                if (axiosClient.config.showLoading) {

                hideLoadingDialog()

                }

                LogUtils.debug(‘网络请求响应Response:’, \n${JsonUtils.stringify(response.data)});

                if (response.status === 200) {

                // @ts-ignore

                const checkResultCode = response.config.checkResultCode

                if (checkResultCode && response.data.errorCode != 0) {

                showToast(response.data.errorMsg)

                return Promise.reject(response)

                }

                return Promise.resolve(response.data);

                } else {

                return Promise.reject(response);

                }

                },

                responseInterceptorCatch: (error) => {

                if (axiosClient.config.showLoading) {

                hideLoadingDialog()

                }

                LogUtils.error(“网络请求响应异常”, error.toString())

                errorHandler(error);

                return Promise.reject(error);

                },

                }

                });

                export default axiosClient;

                封装后使用

                经过封装后,使用变得很简单了。示例如下:

                import axiosClient from ‘./AxiosRequest’

                let baseUrl = “https://www.wanandroid.com/”

                //返回数据结构定义

                interface HomeModelIssueList {

                releaseTime: number;

                type: string;

                date: number;

                publishTime: number;

                count: number;

                }

                interface HomeModel {

                issueList: HomeModelIssueList[];

                itemList: HomeModelIssueList[];

                nextPageUrl: string;

                nextPublishTime: number;

                newestIssueType: string;

                }

                interface BannerDataModelData {

                desc: string;

                id: number;

                imagePath: string;

                isVisible: number;

                order: number;

                title: string;

                type: number;

                url: string;

                }

                /**

                • 请求首页数据-axios客户端请求
                • @param date
                • @returns

                  */

                  export function getHomeListAxios(date: string = “”) {

                  return axiosClient.get({

                  url: baseUrl + “api/v2/feed”,

                  params: { “date”: date },

                  showLoading: true

                  // headers: { “Accept”: “application/json” } as AxiosRequestHeaders

                  })

                  }

                  /**

                  • 获取分类详情接口
                  • @param id
                  • @param start

                    */

                    export function getCategoryDetailList(id: number, start: number) {

                    return axiosClient.get(

                    自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

                    深知大多数HarmonyOS鸿蒙开发工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

                    因此收集整理了一份《2024年HarmonyOS鸿蒙开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

                    既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上HarmonyOS鸿蒙开发知识点,真正体系化!

                    由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新

                    如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注鸿蒙获取)

                    一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

                    712669440999)]

                    [外链图片转存中…(img-pBV6L7Ct-1712669440999)]

                    既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上HarmonyOS鸿蒙开发知识点,真正体系化!

                    由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新

                    如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注鸿蒙获取)

                    [外链图片转存中…(img-pjNilSbE-1712669440999)]

                    一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!