鸿蒙Harmony应用开发,数据驾驶舱网络请求(Axios) 封装

鸿蒙Harmony应用开发,数据驾驶舱网络请求(Axios) 封装

在进行网络请求的封装之前,先来分析一下我们项目所用到的接口的基本情况: 1. 在请求的接口中添加了签名。

2.在非登录接口中添加了token。 基于以上基本的情况。我们开始来对Axios做封装。

首先我们需要在根目录的oh-package.json5文件的dependencies中添加 axios的依赖

"@ohos/axios": "^2.1.1",

前面我们已经介绍了我们的接口请求中的2个必要因素是签名和token,现在我们开始对这2块的实现开始介绍

  • 签名的生成

    我们的签名是将当前所有的请求参数加上当前的时间戳来生成的签名,所以们把请求中的参数做遍历放到一个数组中

    在添加一个当前时间戳,以及生成的签名作为新的请求参数

    private generateSignature(params: RequestParams): RequestParams {
    const time = Date.now().toString().substr(0, 10);
    let str = pref + "&";

    const allParams: RequestParams = {};
    Object.keys(params).forEach((key) => {
    allParams[key] = params[key];
    });
    allParams['timestamp'] = time;

    const sortedKeys = Object.keys(allParams).sort();

    sortedKeys.forEach((key) => {
    const value = allParams[key];
    if (typeof value !== 'object' && value !== null) {
    if (key === "timestamp") {
    str += ${key}=${time}&;
    } else if (key !== "sign") {
    str += ${key}=${decodeURIComponent(String(value))}&;
    }
    }
    });
    str += suff;
    allParams['sign'] = CryptoJS.MD5(str).toString()
    return allParams
    }

  • 请求头token

    我们在登录接口获取到token后存储到preferences中,然后在再请求头添加类似的代码

    headers.set('Authorization', token);
    

接下来我们创建一个PolarisHttp.ets开始对基本的get ,post ,put,patch等方法的封装

首先我们需要创建一个网络请求对象 PolarisHttpRequest,定义基础的变量

config: HttpRequestConfig;  //请求配置参数
interceptorHooks?: InterceptorHooks; //拦截器
instance: AxiosInstance; //阿修罗实例

阿修罗网络请求核心代码:

request<T = CommonType>(config: HttpRequestConfig): Promise<T> {
  return new Promise<T>((resolve, reject) => {
    this.instance
      .request<CommonType, T>(config)
      .then(res => {
        resolve(res);
      })
      .catch((err: Error) => {
        LogUtils.error("网络请求Request异常:", err.toString());
        if (err instanceof AxiosError) {
          showToast(err.message)
        }
        reject(err);
      });
  });
}
  • GET 请求封装:

    public get<T = CommonType>(config: HttpRequestConfig): Promise<T> {
      // 确保 params 存在
      if (!config.params) {
        config.params = {};
      }
    ​
      const allParams: RequestParams = this.generateSignature(config.params);
      // Object.keys(config.params).forEach(key => {
      //   allParams[key] = config.params[key];
      // });
      // 创建新的 headers 对象
      const headers = new AxiosHeaders(config.headers);
      return new Promise<T>((resolve, reject) => {
        const getTokenAndSendRequest = () => {
          if (!config.isLoginState) {
            UserLoginHelper.getUserToken().then(token => {
              if (token && typeof token === 'string') {
                LogUtils.error('网络请求Request Authorization', token);
                headers.set('Authorization', token);
              } else {
                LogUtils.error('网络请求Request 请求未获取的Token信息');
              }
              sendRequest();
            }).catch(reject);
          } else {
            sendRequest();
          }
        };
        const sendRequest = () => {
          // 构建新的配置对象
          const newConfig: HttpRequestConfig = {
            method: 'GET',
            url: config.url,
            params: allParams,
            headers: headers,
            data: config.data,
            timeout: config.timeout,
            responseType: config.responseType
          };
          // 发送请求
          this.request<T>(newConfig).then(resolve).catch(reject);
        };
        getTokenAndSendRequest();
      });
    }
    
  • POST请求封装:

    public post<T = CommonType>(config: HttpRequestConfig): Promise<T> {
      // 确保 data 存在
      if (!config.data) {
        config.data = {};
      }
      let allData: RequestParams = {};
      // 复制原有数据
      Object.keys(config.data).forEach(key => {
        allData[key] = config.data[key];
      });
      // 使用 generateSignature 方法生成签名
      allData = this.generateSignature(allData);
      // 创建新的 headers 对象
      const headers = new AxiosHeaders(config.headers);
    ​
      // 使用Promise来处理异步token获取
      return new Promise<T>((resolve, reject) => {
        const getTokenAndSendRequest = () => {
          if (!config.isLoginState) {
            LogUtils.error('网络请求Request--Authorization...token..!config.isLoginState');
            UserLoginHelper.getUserToken().then(token => {
              if (token && typeof token === 'string') {
                LogUtils.error('网络请求Request--Authorization', token);
                headers.set('Authorization', token);
              } else {
                LogUtils.error('网络请求Request--Authorization--请求未获取的Token信息');
              }
              sendRequest();
            }).catch(reject);
          } else {
            LogUtils.error('网络请求Request--Authorization...token..config.isLoginState');
            sendRequest();
          }
        };
        const sendRequest = () => {
          // 构建新的配置对象
          const newConfig: HttpRequestConfig = {
            method: 'POST',
            url: config.url,
            data: allData,
            headers: headers,
            timeout: config.timeout,
            responseType: config.responseType
          };
          // 发送请求
          this.request<T>(newConfig).then(resolve).catch(reject);
        };
        getTokenAndSendRequest();
      });
    ​
    ​
      // // 构建新的配置对象
      // const newConfig: HttpRequestConfig = {
      //   method: 'POST',
      //   url: config.url,
      //   data: allData,
      //   headers: headers,
      //   timeout: config.timeout,
      //   responseType: config.responseType
      // };
      // // 返回请求
      // return this.request<T>(newConfig);
    }
    

我们可以看到上述的get 请求和post请求都用了2次回调,因为我们的 preferences数据的获取是一个异步过程(因为js我不是很熟悉如果你有好的实现,也可以分享下) 我们需要先异步获取到token 然后在添加到请求头中当中去.

使用示例

const httpClient = new PolarisHttpRequest({
  baseURL: 'https://api.example.com',
  timeout: 5000,
  interceptorHooks: {
    requestInterceptor: (config) => {
      // 请求拦截逻辑
      return config;
    },
    responseInterceptor: (response) => {
      // 响应拦截逻辑
      return response;
    }
  }
});
​
// GET请求示例
httpClient.get<ApiResponse<UserInfo>>({
  url: '/user/info',
  params: { userId: 123 }
}).then(response => {
  console.log(response.data);
}).catch(error => {
  console.error(error);
});
​
// POST请求示例
httpClient.post<ApiResponse<LoginResult>>({
  url: '/user/login',
  data: { username: 'example', password: 'password' }
}).then(response => {
  console.log(response.data);
}).catch(error => {
  console.error(error);
});

注意事项

  1. 确保在使用前正确配置baseURL和其他必要的选项。
  2. generateSignature方法使用了特定的签名算法,请根据实际需求调整。
  3. 对于不同的环境(开发、测试、生产),可能需要不同的配置,建议使用环境变量或配置文件管理。

至此,您可以在ArkTS应用中更加方便地管理和发送HTTP请求,同时保证了请求的安全性和一致性。封装类提供的拦截器和错误处理机制可以大大简化API调用的复杂度。

完整项目下载地址

相关推荐
- 羊羊不超越 -18 分钟前
App渠道来源追踪方案全面分析(iOS/Android/鸿蒙)
android·ios·harmonyos
长弓三石2 小时前
鸿蒙网络编程系列44-仓颉版HttpRequest上传文件示例
前端·网络·华为·harmonyos·鸿蒙
xianwu5432 小时前
反向代理模块
linux·开发语言·网络·git
follycat2 小时前
[极客大挑战 2019]HTTP 1
网络·网络协议·http·网络安全
xiaoxiongip6663 小时前
HTTP 和 HTTPS
网络·爬虫·网络协议·tcp/ip·http·https·ip
JaneJiazhao3 小时前
HTTPSOK:智能SSL证书管理的新选择
网络·网络协议·ssl
CXDNW3 小时前
【网络面试篇】HTTP(2)(笔记)——http、https、http1.1、http2.0
网络·笔记·http·面试·https·http2.0
无所谓จุ๊บ4 小时前
树莓派开发相关知识十 -小试服务器
服务器·网络·树莓派
SameX4 小时前
鸿蒙 Next 电商应用安全支付与密码保护实践
前端·harmonyos
道法自然04024 小时前
Ethernet 系列(8)-- 基础学习::ARP
网络·学习·智能路由器