HarmonyOS鸿蒙Next之HTTP请求二次封装实战

HarmonyOS鸿蒙Next之HTTP请求二次封装实战

一、封装目标设计

功能特性

  • 请求方法简化:支持 get()/post()/put()/delete() 快捷方法
  • 全局配置:设置基础URL、超时时间、公共Headers
  • 拦截器系统:请求/响应双向拦截管道
  • 多数据格式:自动处理 FormData/JSON 格式转换
  • 取消请求:通过唯一标识取消进行中的请求

类型定义

interface RequestConfig {
  url: string
  method?: HttpRequestMethod
  params?: Record<string, any>
  data?: any
  headers?: Record<string, string>
  timeout?: number
}

interface HttpResponse<T = any> {
  status: number
  data: T
  headers: Record<string, string>
}

interface HttpError extends Error {
  code?: number
  config: RequestConfig
  response?: HttpResponse
}

二、核心实现代码

步骤1:创建HttpClient类

export class HttpClient {
  private instance: http.HttpClient
  private interceptors = {
    request: [] as RequestInterceptor[],
    response: [] as ResponseInterceptor[]
  }

  constructor(private baseConfig: RequestConfig = {}) {
    this.instance = http.createHttp()
  }

  // 全局配置更新
  setConfig(config: Partial<RequestConfig>) {
    this.baseConfig = {...this.baseConfig, ...config}
  }
}

步骤2:实现基础请求方法

async request<T = any>(config: RequestConfig): Promise<HttpResponse<T>> {
  const mergedConfig = this.mergeConfig(config)
  
  // 执行请求拦截
  const processedConfig = await this.runRequestInterceptors(mergedConfig)
  
  try {
    const response = await this.dispatchRequest(processedConfig)
    // 执行响应拦截
    return this.runResponseInterceptors(response)
  } catch (error) {
    throw this.normalizeError(error, processedConfig)
  }
}

private dispatchRequest(config: RequestConfig): Promise<HttpResponse> {
  return new Promise((resolve, reject) => {
    const httpRequest = this.instance.request(
      this.buildFullUrl(config.url),
      {
        method: config.method || HttpMethod.GET,
        header: config.headers,
        extraData: config.data,
        connectTimeout: config.timeout
      },
      (err, data) => {
        if (err) {
          reject(err)
        } else {
          resolve({
            status: data.responseCode,
            data: this.parseResponseData(data),
            headers: data.header 
          })
        }
      }
    )
    
    // 存储请求对象用于取消
    this.storeRequest(httpRequest, config)
  })
}

步骤3:添加拦截器支持

// 请求拦截器类型
type RequestInterceptor = (config: RequestConfig) => Promise<RequestConfig>

// 响应拦截器类型
type ResponseInterceptor = (response: HttpResponse) => Promise<HttpResponse>

// 添加拦截器
useRequestInterceptor(interceptor: RequestInterceptor) {
  this.interceptors.request.push(interceptor)
}

useResponseInterceptor(interceptor: ResponseInterceptor) {
  this.interceptors.response.push(interceptor)
}

// 执行拦截器链
private async runRequestInterceptors(config: RequestConfig) {
  let processedConfig = config
  for (const interceptor of this.interceptors.request) {
    processedConfig = await interceptor(processedConfig)
  }
  return processedConfig
}

三、快捷方法封装

// 快捷方法实现
get<T = any>(url: string, params?: Record<string, any>, config?: Omit<RequestConfig, 'url' | 'params'>) {
  return this.request<T>({
    url,
    method: HttpMethod.GET,
    params,
    ...config
  })
}

post<T = any>(url: string, data?: any, config?: Omit<RequestConfig, 'url' | 'data'>) {
  return this.request<T>({
    url,
    method: HttpMethod.POST,
    data,
    ...config
  })
}

// 文件上传封装
uploadFile(url: string, file: FileItem) {
  const formData = new FormData()
  formData.append('file', file.uri, {
    filename: file.name,
    contentType: file.type
  })
  
  return this.post(url, formData, {
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  })
}

四、使用示例

基础调用

const http = new HttpClient({
  baseURL: 'https://xxx.xx',
  timeout: 15000
})

// GET请求
const res = await http.get('/user', { id: 123 })

// POST请求
await http.post('/login', {
  username: 'admin',
  password: '******'
})

拦截器应用

// 添加请求拦截器
http.useRequestInterceptor(async (config) => {
  const token = AppStorage.get('token')
  if (token) {
    config.headers = {
      ...config.headers,
      Authorization: `Bearer ${token}`
    }
  }
  return config
})

// 添加响应拦截器
http.useResponseInterceptor(async (response) => {
  if (response.status === 401) {
    router.navigateTo('/login')
    throw new Error('登录过期')
  }
  return response
})

更多关于HarmonyOS鸿蒙Next之HTTP请求二次封装实战的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

为什么我的类型不行出现any,出现就报错

更多关于HarmonyOS鸿蒙Next之HTTP请求二次封装实战的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,HTTP请求的二次封装主要是为了简化开发者在应用中进行网络请求的复杂性。鸿蒙提供了@ohos.net.http模块来处理HTTP请求,开发者可以通过封装该模块来实现更加便捷的网络请求功能。

首先,鸿蒙的@ohos.net.http模块提供了HttpRequest类,用于发起HTTP请求。开发者可以通过创建HttpRequest实例,并设置URL、请求方法(GET、POST等)、请求头、请求体等参数来发起网络请求。

在二次封装时,可以通过创建一个自定义的HttpClient类,将HttpRequest的调用封装在内部。例如,可以定义一个get方法来处理GET请求,post方法处理POST请求。在这些方法内部,可以统一处理请求头、请求体、超时设置、错误处理等逻辑。

此外,鸿蒙还支持异步请求,开发者可以通过Promiseasync/await来处理异步请求的响应。在封装时,可以将异步请求的结果通过回调函数或Promise返回给调用者,以便于在应用中进行进一步处理。

例如,以下是一个简单的HTTP GET请求的二次封装示例:

import http from '@ohos.net.http';

class HttpClient {
  async get(url: string, headers?: Record<string, string>) {
    const httpRequest = http.createHttp();
    const options = {
      method: http.RequestMethod.GET,
      header: headers,
    };
    return httpRequest.request(url, options);
  }
}

通过这种方式,开发者可以在应用中直接调用HttpClientget方法,而不需要每次都手动创建HttpRequest实例和设置参数。

总之,鸿蒙Next中HTTP请求的二次封装可以通过自定义HttpClient类来实现,简化网络请求的调用和处理,提高开发效率。

在HarmonyOS鸿蒙Next中,HTTP请求的二次封装可以提高代码复用性和可维护性。首先,创建一个基础的HTTP请求类,封装常用的GET、POST等方法。其次,定义统一的请求参数和响应处理逻辑,如添加公共请求头、处理错误码等。最后,根据业务需求扩展特定API的请求方法,确保接口调用简洁高效。通过二次封装,开发者可以更专注于业务逻辑的实现,提升开发效率。

回到顶部