HarmonyOS鸿蒙应用开发——HTTP网络访问与封装

2023-12-14 12:33:40

网络基础

基本使用

鸿蒙应用发起HTTP请求的基本使用,如下:

  • 导入http模块
  • 创建httpRequest对象
  • 发起http请求,并处理响应结果

第一、导入http模块:

import http from '@ohos.net.http'

第二、创建httpRequest对象,注意的是每一个httpRequest对象对应一个http请求任务,不可复用。

 const httpRequest = http.createHttp()

第三、发起请求,比如POST请求

 httpRequest.request(
  // 请求url地址
  url,
  {
    // 请求方式
    method: http.RequestMethod.POST,
    // 请求的额外数据。
    extraData: {
      "param1": "value1",
      "param2": "value2",
    },
    // 可选,默认为60s
    connectTimeout: 60000,
    // 可选,默认为60s
    readTimeout: 60000,
    // 开发者根据自身业务需要添加header字段
    header: {
      'Content-Type': 'application/json'
    }
  })
  .then((data) => { 
  if (data.responseCode === http.ResponseCode.OK) {
  	// 处理响应结果
  	// data.result为服务器返回的业务数据
    console.info('Result:' + data.result);
    console.info('code:' + data.responseCode);
  }
}).catch((err) => {
 console.info('error:' + JSON.stringify(err));
});

最后需要声明网络权限,在module.josn5文件中声明:

{
    "module" : {
        "requestPermissions":[
           {
             "name": "ohos.permission.INTERNET"
           }
        ]
    }
}

上面就是网络请求的简单使用,接下来通过Promise来封装一个网络请求库,统一管理请求参数、响应数据、日志的输出等,对外屏蔽了细节,使用者只需定义业务数据的实体类以及调用即可。

封装

以**玩Android**开放接口为测试用例

定义业务数据的实体类,通过泛型来接收不同的数据类型:

export class ResponseResult<T> {
  errorCode: number;
  errorMsg: string;
  data?: T | Object | string;
}

把各种请求方式用枚举声明RequestMethod

export enum RequestMethod {
  OPTIONS,
  GET,
  HEAD,
  POST ,
  PUT,
  DELETE,
  TRACE,
  CONNECT
}

其实在http模块中已经有对应的枚举,之所以再用一个新枚举来声明,是简化使用,同时也是将http模块相关细节屏蔽掉不对外开放,这样可以灵活替换网络库。

定义一个HttpUtils类实现:

const  TAG = "HttpUtils"
const BASE_URL = "https://www.wanandroid.com"
export class HttpUtils{
  public static readonly SUCCESS_CODE: number = 0
  public static readonly READ_TIME_OUT = 60 * 1000
  public static readonly CONNECT_TIME_OUT = 60 * 1000
  private baseUrl: string = ""

  constructor(baseUrl: string) {
    this.baseUrl = baseUrl
  }

  private methodName(method: RequestMethod): http.RequestMethod {
    switch (method){
      case RequestMethod.OPTIONS:{
        return http.RequestMethod.OPTIONS
      }
      case RequestMethod.GET:{
        return http.RequestMethod.GET
      }
      case RequestMethod.HEAD:{
        return http.RequestMethod.HEAD
      }
      case RequestMethod.POST:{
        return http.RequestMethod.POST
      }
      case RequestMethod.PUT:{
        return http.RequestMethod.PUT
      }
      case RequestMethod.DELETE:{
        return http.RequestMethod.DELETE
      }
      case RequestMethod.TRACE:{
        return http.RequestMethod.TRACE
      }
      case RequestMethod.CONNECT:{
        return http.RequestMethod.CONNECT
      }

    }

  }

  request<T>(path: string, reqMethod: RequestMethod, parameter: Map<string, Object> = null): Promise<T | null> {
    // 注意的是每一个httpRequest对象对应一个http请求任务,不可复用。
    const httpRequest = http.createHttp()
    const method = this.methodName(reqMethod)
    let extraData = {}
    let url = `${this.baseUrl}/${path}`
    if (parameter != null) {
      switch (reqMethod) {
        case RequestMethod.POST: {
          extraData = Object.fromEntries(parameter)
          break;
        }
        case RequestMethod.GET: {
          const urlParams = Object.keys(parameter).map(key => `${key}=${parameter[key]}`).join('&')
          if (url.includes("?")) {
            url = `${url}${urlParams}`
          } else {
            url = `${url}?${urlParams}`
          }
          break;
        }
      }
    }

    LogUtils.debug(TAG, "==================Request====================")
    LogUtils.debug(TAG, "url: " + url)
    LogUtils.debug(TAG, "method: " + method.toString())
    if (reqMethod == RequestMethod.POST)
      LogUtils.debug(TAG, "extraData: " + JSON.stringify(parameter, null, 2))
    return new Promise((resolve, reject) => {
      httpRequest.request(url,
        {
          method,
          readTimeout: HttpUtils.READ_TIME_OUT,
          connectTimeout: HttpUtils.CONNECT_TIME_OUT,
          header: {
            'Content-Type': 'application/json'
          },
          extraData
        }
      ).then((value) => {
        LogUtils.debug(TAG, "==================Response====================")
        LogUtils.debug(TAG, "url: " + url)
        LogUtils.debug(TAG, "method: " + method.toString())
        LogUtils.debug(TAG, "header: " + JSON.stringify(value.header, null, 2))
        LogUtils.debug(TAG, "responseCode: " + value.responseCode)
        LogUtils.debug(TAG, "resultType: " + value.resultType)
        if (value.responseCode == http.ResponseCode.OK) {
          let result: ResponseResult<T> = JSON.parse(value.result.toString())
          LogUtils.debug(TAG, "body: " + JSON.stringify(result, null, 2))
          if (result.errorCode == HttpUtils.SUCCESS_CODE) {
            resolve(result.data as T)
          } else {
            reject(result.errorMsg)
          }
        } else {
          reject("请求失败")
        }
      }).catch((reason) => {
        reject(reason)
      })
    })
  }

  get<T>(path: string, parameter: Map<string, Object> = null): Promise<T | null> {
    return this.request<T>(path, RequestMethod.GET, parameter)
  }

  post<T>(path: string, parameter: Map<string, Object> = null): Promise<T | null> {
    return this.request<T>(path, RequestMethod.POST, parameter)
  }

  delete<T>(path: string, parameter: Map<string, Object> = null): Promise<T | null> {
    return this.request<T>(path, RequestMethod.DELETE, parameter)
  }

  put<T>(path: string, parameter: Map<string, Object> = null): Promise<T | null> {
    return this.request<T>(path, RequestMethod.PUT, parameter)
  }

}
const YiNet = new HttpUtils(BASE_URL)
export default YiNet

使用发起网络请求:

  aboutToAppear() {
    let map = new Map<string,string>()
    map["cid"] = 294
    YiNet.get<ArticleList>("project/list/1/json",map).then((data)=>{
      this.data = JSON.stringify(data, null, 2)
    })

    let map2 = new Map<string,string>()
    map2["username"] = "123"
    map2["password"] = "123456"
    YiNet.post<User>("user/login",map2).then((data)=>{
      this.data = JSON.stringify(data, null, 2)
    }).catch((err)=>{
      Prompt.showToast({message:err})
    })
  }

日志输出:

在这里插入图片描述

参考

  • https://developer.huawei.com/consumer/cn/training/course/slightMooc/C101667364948559963?ha_linker=eyJ0cyI6MTcwMjE3NzI3OTYyMywiaWQiOiI4MmM3ZTI1MmFmMDJlMDZiODBmOGU1ZDM5ZTI5YmMyOCJ9
  • https://www.wanandroid.com/blog/show/2

文章来源:https://blog.csdn.net/hzw2017/article/details/134910847
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。