引言
在鸿蒙(HarmonyOS)应用开发中,网络通信是实现数据交互的核心能力。优雅的网络层封装不仅能提升代码的可维护性和复用性,还能统一异常处理机制,为后续的业务扩展奠定坚实基础。本文将通过一个实战案例,详细介绍如何构建一个功能完备、易于使用的网络请求客户端。
一、核心设计理念
1.1 架构设计原则
在开始编码之前,我们确立了以下设计原则:
- 单一职责:网络层专注于HTTP通信,业务逻辑与数据转换分离
- 开闭原则:支持扩展新的HTTP方法,无需修改现有代码
- 接口隔离:提供简洁的API,隐藏底层实现复杂性
1.2 技术栈选择
- 基础框架 :鸿蒙官方
@kit.NetworkKit模块,提供原生HTTP能力 - 设计模式:采用单例模式,确保全局配置一致性
二、网络层实现细节
2.1 数据类型定义
typescript
/**
* 标准API响应结构定义
* @property code - 业务状态码(如:"000000"表示成功)
* @property message - 服务器返回的业务提示信息
* @property data - 实际返回的业务数据内容
*/
export interface MyResponseType {
code: string;
message: string;
data: string;
}
这一接口定义不仅规范了前后端数据契约,还为TypeScript提供了完整的类型提示,确保开发过程中及早发现类型不匹配问题。
2.2 HttpClient核心实现
typescript
/**
* HTTP客户端(单例模式)
* 封装HTTP请求方法,提供类型安全的请求接口
*/
export class HttpClient {
private static instance: HttpClient;
// API服务端基础地址
private baseUrl: string = 'https://xxx.xxxx.xxxx.xxxx:xxxx/';
// 默认请求头配置
private headers: Record<string, string> = {
'Content-Type': 'application/json', // 指定请求体为JSON格式
'User-Agent': 'HarmonyOS-App' // 标识客户端类型,便于服务端统计
};
/**
* 获取HttpClient单例实例
* @returns 全局唯一的HttpClient实例
* @example
* const client = HttpClient.getInstance();
*/
static getInstance(): HttpClient {
if (!HttpClient.instance) {
HttpClient.instance = new HttpClient(); // 首次调用时创建实例
}
return HttpClient.instance;
}
// 私有构造函数,防止外部实例化
private constructor() {}
}
2.3 核心请求方法实现
typescript
/**
* 通用HTTP请求方法
* @param method - HTTP方法(GET、POST等)
* @param url - 请求地址(相对路径或完整URL)
* @param data - 请求体数据
* @returns 解析后的响应数据
*/
private async request<T>(method: http.RequestMethod, url: string, data?: string): Promise<T> {
const httpRequest = http.createHttp();
// 智能URL拼接:支持绝对路径和相对路径
const fullUrl = url.startsWith('http') ? url : `${this.baseUrl}${url}`;
try {
// 发起网络请求
const response = await httpRequest.request(fullUrl, {
method,
header: this.headers,
extraData: data ? JSON.stringify(data) : undefined
});
// HTTP状态码校验(2xx视为成功)
if (response.responseCode >= 200 && response.responseCode < 300) {
return JSON.parse(response.result as string);
} else {
// 非2xx状态码抛出异常
throw new Error(`HTTP ${response.responseCode}: ${response.result}`);
}
} catch (error) {
// 统一异常转换和处理
const err = error as BusinessError;
console.error(`请求失败: ${err.code} ${err.message}`);
throw new Error(`HTTP ${error}`);
} finally {
// 确保网络资源释放
httpRequest.destroy();
}
}
2.4 便捷方法封装
typescript
/**
* POST请求快捷方法
* @param endpoint - API端点路径
* @param body - 请求体对象
* @returns Promise解析后的响应数据
* @example
* client.post<ResponseType, RequestBody>('api/login', {username: 'test'});
*/
async post<T, U>(endpoint: string, body: U): Promise<T> {
// 自动序列化请求体为JSON字符串
return this.request(http.RequestMethod.POST, endpoint, JSON.stringify(body));
}
泛型参数设计:
T:指定响应数据类型,提供编译时类型安全U:指定请求体类型,确保请求数据结构正确性
三、业务层调用示例
3.1 页面调用实现
typescript
/**
* 处理网络请求的异步方法
*/
private async handleRequest() {
try {
// 获取HttpClient单例实例
const client = HttpClient.getInstance();
// 发起POST请求,指定响应类型为MyResponseType,请求体类型为string
const response = await client.post<MyResponseType, string>('baidu/wenxin', '你好');
// 调试输出:便于开发阶段验证数据格式
console.log("请求结果:");
console.log(JSON.stringify(response));
// 典型响应示例:
// {
// "code": "000000",
// "msg": "请求成功",
// "data": "您好!有什么我可以帮助您的吗?"
// }
} catch (error) {
// 统一错误处理:日志记录和用户提示
console.error('请求失败:', error);
this.message = '请求异常';
}
}
完整代码
ts
import { http } from '@kit.NetworkKit'; // 导入新版网络模块
import { BusinessError } from '@kit.BasicServicesKit';
/**
* 定义标准API响应结构
* @property code - 响应状态码(如:200成功,500服务器错误)
* @property message - 服务器返回的提示信息
* @property data - 实际返回的业务数据内容
*/
export interface MyResponseType {
code: string;
message: string;
data: string;
}
/**
* HttpClient网络请求客户端(单例模式)
* 封装HTTP请求方法,提供POST请求的快捷方式
*/
export class HttpClient {
private static instance: HttpClient; // 单例实例
// API基础地址
private baseUrl: string = 'https://xxx.xxxx.xxxx.xxxx:xxxx/';
// 默认请求头配置
private headers: Record<string, string> = {
'Content-Type': 'application/json', // 请求体格式为JSON
'User-Agent': 'HarmonyOS-App' // 标识客户端类型
};
/**
* 获取HttpClient单例实例
* @returns 全局唯一的HttpClient实例
* @example
* const client = HttpClient.getInstance();
*/
static getInstance(): HttpClient {
if (!HttpClient.instance) {
HttpClient.instance = new HttpClient(); // 懒加载创建实例
}
return HttpClient.instance;
}
// 通用请求方法
private async request<T>(method: http.RequestMethod, url: string, data?: string): Promise<T> {
const httpRequest = http.createHttp();
const fullUrl = url.startsWith('http') ? url : `${this.baseUrl}${url}`;
try {
const response = await httpRequest.request(fullUrl, {
method,
header: this.headers,
extraData: data ? JSON.stringify(data) : undefined
});
if (response.responseCode >= 200 && response.responseCode < 300) {
return JSON.parse(response.result as string);
} else {
throw new Error(`HTTP ${response.responseCode}: ${response.result}`);
}
} catch (error) {
const err = error as BusinessError;
console.error(`请求失败: ${err.code} ${err.message}`);
throw new Error(`HTTP ${error}`);
} finally {
httpRequest.destroy();
}
}
/**
* 发送POST请求的快捷方法
* @param endpoint - 接口端点路径(如:'user/login')
* @param body - 请求体对象(自动序列化为JSON)
* @returns Promise解析后的响应数据
* @example
* client.post<ResponseType, RequestBody>('api/login', {username: 'test'});
*/
async post<T, U>(endpoint: string, body: U): Promise<T> {
return this.request(http.RequestMethod.POST, endpoint, JSON.stringify(body));
}
}