HarmonyOS项目开发经历-鸿蒙原生http封装

242 阅读6分钟

我们在进行鸿蒙应用开发时,有必要将数据请求模块进行统一的封装,利于代码复用,提高开发效率。

以下我将常用的三种请求get、post、pull进行了统一封装,方便项目开发中使用。

思路:将第一层的数据使用泛型进行封装,在发起请求时只需传入第二层的数据类型即可获取到第二层数据,使用起来方便高效。

get

  //统一封装get请求
  static async get<T>(url: string, extraData?: Object):Promise<T> {
    try {
      const httpRequest = http.createHttp()
​
      let options: http.HttpRequestOptions = {
        header: {
          "Content-Type": "application/json"
        },
        expectDataType: http.HttpDataType.OBJECT
      }
      // 1. 判断extraData可选参数如果不为空,则要将其追加到options对象中
      if (extraData) {
        options.extraData = extraData
      }
      // 1.0 获取token传给服务器
      let token = await PreferencesManager.getData('token', 'token', '')
      if (token && options.header) {
        options.header['Authorization'] = token
      }
​
      // 2.0 发请求
      url = baseUrl + url
      let res = await httpRequest.request(url, options)
​
      //   3.0 处理响应判断code
      // 增加服务器响应的code如果为401表示token失效,则重新登录获取新的有效token
      let resdata = res.result as iResponseModel<T>
      console.log('code', resdata.code)
      // 如果服务器响应回来的数据不为10000,则表示有错误,则提示出错误信息
      if (resdata.code !== 200) {
        // 如果服务器响应回来的code为401表示token失效,应该重新登录
        if (resdata.code === 401) {
          //   token失效,重新登录
          promptAction.showToast({ message: 'token失效,请重新登录' })
          router.replaceUrl({ url: 'pages/LoginPage' })
        } else {
          console.log('ddd', JSON.stringify(resdata))
        }
      }
      //   4. 将服务器的数据返回
      return resdata.data as T
    } catch (err) {
      promptAction.showToast({ message: 'get请求网络异常' })
      return Promise.reject(err)
    }
​
  }

post

  // 1.统一封装post请求方法
  static async post<T>(url: string, extraData?: Object) :Promise<T>{
    try {
      const httpReq = http.createHttp()
​
      let options: http.HttpRequestOptions = {
        method: http.RequestMethod.POST,
        header: {
          "Content-Type": "application/json"
        },
        expectDataType: http.HttpDataType.OBJECT
      }
​
      // 1. 判断extraData可选参数如果不为空,则要将其追加到options对象中
      if (extraData) {
        options.extraData = extraData
      }
      // 2. 从首选项获取token,如果需要token就加进请求头
​
      let token = await PreferencesManager.getData('token', 'token', '')
      // 使用user?写法,就能规避bug:在undefined上点出token这个属性报错
      if (token && options.header) {
        options.header['Authorization'] = token
      }
​
      // 3. 将动态构建好的options参数和url传给request->发请求获取服务器的响应数据
      url = baseUrl + url // 将用户传入的路径与基本地址拼接成一个完整的url地址,将来java后端发布接口的baseurl改变,我们只需要改变baseurl
      let res = await httpReq.request(url, options)
​
      // 增加服务器响应的code如果为401表示token失效,则重新登录获取新的有效token
      let resdata = res.result as iResponseModel<T>
      console.log('code', resdata.code)
      // 如果服务器响应回来的数据不为10000,则表示有错误,则提示出错误信息
      if (resdata.code !== 200) {
        // 如果服务器响应回来的code为401表示token失效,应该重新登录
        if (resdata.code === 401) {
          //   token失效,重新登录
          promptAction.showToast({ message: 'token失效,请重新登录' })
          router.replaceUrl({ url: 'pages/LoginPage' })
        } else {
          promptAction.showToast({ message: resdata.message })
        }
      }
​
      //   4. 将服务器的数据返回
      return resdata.data as T
    } catch (err) {
      promptAction.showToast({ message: '网络请求错误' })
      return Promise.reject(err)
    }
  }

pull

  //put请求
  static async put(url: string, extraData?: Object) {
    try {
      const httpRequest = http.createHttp()
​
      let options: http.HttpRequestOptions = {
        method: http.RequestMethod.PUT,
        header: {
          "Content-Type": "application/json"
        },
        expectDataType: http.HttpDataType.OBJECT
      }
      // 1. 判断extraData可选参数如果不为空,则要将其追加到options对象中
      if (extraData) {
        options.extraData = extraData
      }
      // 1.0 获取token传给服务器
      let token = await PreferencesManager.getData('token', 'token', '')
      if (token && options.header) {
        options.header['Authorization'] = token
      }
​
      // 2.0 发请求
      url = baseUrl + url
      let res = await httpRequest.request(url, options)
​
      //   3.0 处理响应判断code不为10000的情况和401的情况
      // 增加服务器响应的code如果为401表示token失效,则重新登录获取新的有效token
      // let resdata = res.result as iResponseModel<T>
      // console.log('code', resdata.code)
      // 如果服务器响应回来的数据不为10000,则表示有错误,则提示出错误信息
      // if (resdata.code !== 200) {
      //   // 如果服务器响应回来的code为401表示token失效,应该重新登录
      //   if (resdata.code === 401) {
      //     //   token失效,重新登录
      //     promptAction.showToast({ message: 'token失效,请重新登录' })
      //     router.replaceUrl({ url: 'pages/LoginPage' })
      //   } else {
      //     console.log('ddd', JSON.stringify(resdata))
      //     // promptAction.showToast({ message: resdata.message })
      //   }
      // }
      //   4. 将服务器的数据返回
      return
    } catch (err) {
      promptAction.showToast({ message: 'get请求网络异常' })
      return Promise.reject(err)
    }
  }

完整代码

// 所有接口返回数据的类型
export interface iResponseModel<T> {
  /**
   * 请求成功10000标志
   */
  code: number;
​
  /**
   * 返回数据
   */
  data: T | null/**
   * 请求成功
   */
  message: string;
​
}
​
// 提取所有请求的ulr中的域名当做一个基本地址
const baseUrl = 'https:/xxx/'export class HdHttp {
  // 1.统一封装post请求方法
  static async post<T>(url: string, extraData?: Object) :Promise<T>{
    try {
      const httpReq = http.createHttp()
​
      let options: http.HttpRequestOptions = {
        method: http.RequestMethod.POST,
        header: {
          "Content-Type": "application/json"
        },
        expectDataType: http.HttpDataType.OBJECT
      }
​
      // 1. 判断extraData可选参数如果不为空,则要将其追加到options对象中
      if (extraData) {
        options.extraData = extraData
      }
      // 2. 从首选项获取token,如果需要token就加进请求头
​
      let token = await PreferencesManager.getData('token', 'token', '')
      // 使用user?写法,就能规避bug:在undefined上点出token这个属性报错
      if (token && options.header) {
        options.header['Authorization'] = token
      }
​
      // 3. 将动态构建好的options参数和url传给request->发请求获取服务器的响应数据
      url = baseUrl + url // 将用户传入的路径与基本地址拼接成一个完整的url地址,将来java后端发布接口的baseurl改变,我们只需要改变baseurl
      let res = await httpReq.request(url, options)
​
      // 增加服务器响应的code如果为401表示token失效,则重新登录获取新的有效token
      let resdata = res.result as iResponseModel<T>
      console.log('code', resdata.code)
      // 如果服务器响应回来的数据不为10000,则表示有错误,则提示出错误信息
      if (resdata.code !== 200) {
        // 如果服务器响应回来的code为401表示token失效,应该重新登录
        if (resdata.code === 401) {
          //   token失效,重新登录
          promptAction.showToast({ message: 'token失效,请重新登录' })
          router.replaceUrl({ url: 'pages/LoginPage' })
        } else {
          promptAction.showToast({ message: resdata.message })
        }
      }
​
      //   4. 将服务器的数据返回
      return resdata.data as T
    } catch (err) {
      promptAction.showToast({ message: '网络请求错误' })
      return Promise.reject(err)
    }
  }
​
  // 2. 如果要向get请求的url传参,有调用者决定来是否在url后面进行拼接
  static async get<T>(url: string, extraData?: Object):Promise<T> {
    try {
      const httpRequest = http.createHttp()
​
      let options: http.HttpRequestOptions = {
        header: {
          "Content-Type": "application/json"
        },
        expectDataType: http.HttpDataType.OBJECT
      }
      // 1. 判断extraData可选参数如果不为空,则要将其追加到options对象中
      if (extraData) {
        options.extraData = extraData
      }
      // 1.0 获取token传给服务器
      let token = await PreferencesManager.getData('token', 'token', '')
      if (token && options.header) {
        options.header['Authorization'] = token
      }
​
      // 2.0 发请求
      url = baseUrl + url
      let res = await httpRequest.request(url, options)
​
      //   3.0 处理响应判断code
      // 增加服务器响应的code如果为401表示token失效,则重新登录获取新的有效token
      let resdata = res.result as iResponseModel<T>
      console.log('code', resdata.code)
      // 如果服务器响应回来的数据不为10000,则表示有错误,则提示出错误信息
      if (resdata.code !== 200) {
        // 如果服务器响应回来的code为401表示token失效,应该重新登录
        if (resdata.code === 401) {
          //   token失效,重新登录
          promptAction.showToast({ message: 'token失效,请重新登录' })
          router.replaceUrl({ url: 'pages/LoginPage' })
        } else {
          console.log('ddd', JSON.stringify(resdata))
        }
      }
      //   4. 将服务器的数据返回
      return resdata.data as T
    } catch (err) {
      promptAction.showToast({ message: 'get请求网络异常' })
      return Promise.reject(err)
    }
​
  }
​
  //put请求
  static async put(url: string, extraData?: Object) {
    try {
      const httpRequest = http.createHttp()
​
      let options: http.HttpRequestOptions = {
        method: http.RequestMethod.PUT,
        header: {
          "Content-Type": "application/json"
        },
        expectDataType: http.HttpDataType.OBJECT
      }
      // 1. 判断extraData可选参数如果不为空,则要将其追加到options对象中
      if (extraData) {
        options.extraData = extraData
      }
      // 1.0 获取token传给服务器
      let token = await PreferencesManager.getData('token', 'token', '')
      if (token && options.header) {
        options.header['Authorization'] = token
      }
​
      // 2.0 发请求
      url = baseUrl + url
      let res = await httpRequest.request(url, options)
​
      //   3.0 处理响应判断code不为10000的情况和401的情况
      // 增加服务器响应的code如果为401表示token失效,则重新登录获取新的有效token
      // let resdata = res.result as iResponseModel<T>
      // console.log('code', resdata.code)
      // 如果服务器响应回来的数据不为10000,则表示有错误,则提示出错误信息
      // if (resdata.code !== 200) {
      //   // 如果服务器响应回来的code为401表示token失效,应该重新登录
      //   if (resdata.code === 401) {
      //     //   token失效,重新登录
      //     promptAction.showToast({ message: 'token失效,请重新登录' })
      //     router.replaceUrl({ url: 'pages/LoginPage' })
      //   } else {
      //     console.log('ddd', JSON.stringify(resdata))
      //     // promptAction.showToast({ message: resdata.message })
      //   }
      // }
      //   4. 将服务器的数据返回
      return
    } catch (err) {
      promptAction.showToast({ message: 'get请求网络异常' })
      return Promise.reject(err)
    }
  }
}