在前端项目中,一般使用axios进行封装request请求的,但是,在鸿蒙中有点不太一样,因为处理起来比较复杂,这里直接使用自带的request请求api进行封装。鸿蒙封装request的难点在于对类型的判断,以及在处理请求的时候遇到的坑,在以下代码中均有处理,可做参考。


准备工作

1 申请基础网络权限-在module.json5中配置
"requestPermissions": [
      {
        "name": "ohos.permission.INTERNET",
      }
   ...
 ]
2 在constants目录中设置baseURL基础地址常量
export const BASE_URL = ''  // 请求基础地址
3 统一导出
export * from './url_var'
4 在utils下新建request.ets文件,导入请求包和baseURL
import http from '@ohos.net.http'
import { BASE_URL } from '../constants'
5 封装泛型工具-models/index.ets
export class ResponseData<T> {
   code: number = 0
   msg: string = ""
   data: T | null = null // 这里应该必须只能这么声明!!!!
}
// 返回的数据类型可能为null,可以用联合类型并赋初始值

封装一个公共的request方法来支持get/post/put/delete方法

http官网链接

import http from '@ohos.net.http'
import { BASE_URL, TOKEN_KEY } from '../constants'
import { ResponseData } from '../models'
import router from '@ohos.router';
import promptAction from '@ohos.promptAction';
import { UserSettingClass } from '.';

const httpRequest = http.createHttp()

async function requestHttp<T>(url: string = "", method: http.RequestMethod = http.RequestMethod.GET, data?: object): Promise<T> {
  let urlStr = BASE_URL + url
  // 这里虽然官方文档说 get类型可以通过extraData传递过去,但是测试证明不可以-还是老老实实的自己拼接吧
  if (method === http.RequestMethod.GET) {
    if (data && Object.keys(data).length) {
      urlStr += "?" + Object.keys(data).map(key =>  {
        if(data[key]){
          return `${key}=${data[key]}`
        }
        return ""
      }).join('&')
    }
  }
  // 设置请求头
  const config: http.HttpRequestOptions = {
    header: {
      'Content-Type': 'application/json',
      "Authorization": AppStorage.Get(TOKEN_KEY) || ""
    },
    method,
    readTimeout: 10000, // 超时时间
    extraData: method === http.RequestMethod.GET ? "" : data
  }
  try {
    const res = await httpRequest.request(urlStr, config)
    if (res.responseCode === 401) {
      promptAction.showToast({ message: 'token超时' })
      AppStorage.Set(TOKEN_KEY, "") // 删除token 这里为什么不用Delete
      new UserSettingClass(getContext()).setUserToken("") // 清空首选项的token
      router.replaceUrl({
        url: 'pages/Login/Login'
      })
      return Promise.reject(new Error("token不存在或超时"))
    }else if(res.responseCode === 404) {
      promptAction.showToast({ message: '请求地址不正确' })
      return Promise.reject(new Error('请求地址不正确'))
    }
    else {
      const result = JSON.parse(res.result as string) as ResponseData<T>
      if (result.code === 200) {
        // 执行成功
        return result.data as T // 直接返回数据
      }
      else {
        promptAction.showToast({ message: '服务器异常' })
        return Promise.reject(new Error(result.msg))
      }
    }
  } catch (error) {
    promptAction.showToast({ message: error.message })
    return Promise.reject(error)
  }
  finally {
    httpRequest.destroy(); // 销毁请求
  }
}

// 导出一个类的静态方法
export class Request {
  static get<T>(url: string, data?: object): Promise<T> {
    return requestHttp<T>(url, http.RequestMethod.GET, data)
  }

  static post<T>(url: string, data?: object): Promise<T> {
    return requestHttp<T>(url, http.RequestMethod.POST, data)
  }

  static delete<T>(url: string, data?: object): Promise<T> {
    return requestHttp<T>(url, http.RequestMethod.DELETE, data)
  }

  static put<T>(url: string, data?: object): Promise<T> {
    return requestHttp<T>(url, http.RequestMethod.PUT, data)
  }
}

总结: 上面请求工具总共处理了这么几件事

  • 封装请求-拼接基础地址-传入参数
  • 解构返回的数据-判断状态
  • 200 认为成功直接返回data数据
  • 200以外 401 认为是token超时
  • 500认为是服务器任务
  • 最后暴露一个类的四个静态方法 可以方便的调用 get/put/delete/post
  • 提交代码
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐