网络抽象层 (core/network)
介绍
@core/network 模块提供网络请求的抽象层,支持:
- 可配置的响应解析:适配不同后端的响应格式
- 拦截器机制:支持请求和响应拦截
- 链式请求助手:简化请求处理流程
- 统一的响应封装:标准化的响应结果
- 自动配置注入:从 DI 容器自动获取配置
核心概念
响应解析器 (ResponseParser)
响应解析器用于解析不同格式的后端响应。通过配置解析器,可以适配任意后端的响应格式。
interface ResponseParser<T> {
isSuccess(response: unknown): boolean;
getData(response: unknown): T | null;
getMessage(response: unknown): string | null;
getCode(response: unknown): number;
}
网络配置 (NetworkConfig)
interface NetworkConfig {
baseUrl: string; // 基础 URL
timeout: number; // 超时时间(毫秒)
responseParser?: ResponseParserConfig; // 响应解析配置
headers?: Record<string, string>; // 默认请求头
enableLog?: boolean; // 是否启用日志
}
interface ResponseParserConfig {
successCode: number; // 成功状态码
dataField: string; // 数据字段名
messageField: string; // 消息字段名
codeField: string; // 状态码字段名
}
快速开始
1. 配置网络模块
import { getContainer, CoreServiceKeys } from '@core/di';
import { AxiosHttpClient, NetworkConfig } from '@core/network';
// 在 EntryAbility 中配置
const NetConf: NetworkConfig = {
baseUrl: "https://api.example.com/",
timeout: 10000,
responseParser: {
successCode: 1000, // 根据后端定义
dataField: 'data',
messageField: 'message',
codeField: 'code'
},
headers: {
'Content-Type': 'application/json'
},
enableLog: true
};
// 注册到 DI 容器
const container = getContainer();
container.register<NetworkConfig>(CoreServiceKeys.ConfigManager, () => NetConf);
// 创建并注册 HTTP 客户端
const httpClient = new AxiosHttpClient(NetConf);
container.register<AxiosHttpClient>(CoreServiceKeys.HttpClient, () => httpClient);
2. 在 DataSource 中使用
import { CoreServiceKeys, getContainer } from "@core/di";
import { AxiosHttpClient, NetworkResult } from "@core/network";
export class UserNetworkDataSourceImpl {
async getUserInfo(id: string): Promise<NetworkResult<User>> {
const httpClient = getContainer().resolve<AxiosHttpClient>(CoreServiceKeys.HttpClient);
const rawResponse = await httpClient.get<Unknown>("user/info", { params: { id } });
return new NetworkResult<User>(rawResponse);
}
}
3. 在 ViewModel 中使用 RequestHelper
推荐方式:使用 fromResult()
import { RequestHelper } from "@core/network";
export class UserViewModel {
loadUserInfo(): void {
RequestHelper.fromResult<User>(this.repository.getUserInfo("123"))
.start(() => this.isLoading = true)
.toast(true) // 自动显示错误提示
.execute()
.then((user: User) => {
this.user = user;
})
.finally(() => this.isLoading = false);
}
}
API 参考
AxiosHttpClient
| 方法 | 说明 |
|---|---|
get<T>(url, options?) |
GET 请求 |
post<T>(url, data?, options?) |
POST 请求 |
put<T>(url, data?, options?) |
PUT 请求 |
delete<T>(url, options?) |
DELETE 请求 |
addInterceptor(interceptor) |
添加拦截器 |
removeInterceptor(interceptor) |
移除拦截器 |
getConfig() |
获取当前配置 |
updateConfig(config) |
更新配置 |
RequestOptions
interface RequestOptions {
headers?: Record<string, string>; // 请求头
timeout?: number; // 超时时间
params?: Record<string, unknown>; // URL 参数
}
NetworkResult
class NetworkResult<T> {
readonly data: T | null; // 响应数据
readonly code: number; // 状态码
readonly message: string | null; // 响应消息
readonly isSuccess: boolean; // 是否成功
readonly rawResponse: unknown; // 原始响应
static success<T>(data: T, message?: string): NetworkResult<T>;
static failure<T>(code: number, message: string): NetworkResult<T>;
static error<T>(error: Error): NetworkResult<T>;
}
RequestHelper
class RequestHelper<T> {
// 从原始响应创建(自动解析)
static from<T>(promise: Promise<unknown>, parser?: ResponseParser<T>): RequestHelper<T>;
// 从 NetworkResult 创建(推荐)
static fromResult<T>(promise: Promise<NetworkResult<T>>): RequestHelper<T>;
start(handler: () => void): RequestHelper<T>;
loading(enable?: boolean): RequestHelper<T>;
toast(enable?: boolean): RequestHelper<T>;
onLoading(show: () => void, hide: () => void): RequestHelper<T>;
onError(callback: (message: string) => void): RequestHelper<T>;
execute(): Promise<T>;
response(): Promise<NetworkResult<T>>;
}
拦截器
创建拦截器
import { HttpInterceptor } from '@core/network';
import type { InternalAxiosRequestConfig, AxiosResponse, AxiosError } from '@ohos/axios';
// Token 拦截器
export class AuthInterceptor implements HttpInterceptor {
name = 'AuthInterceptor';
priority = 10;
async onRequest(config: InternalAxiosRequestConfig): Promise<InternalAxiosRequestConfig> {
const token = getUserState().getToken();
if (token) {
const headers = AxiosHeaders.from(config.headers);
headers.set('Authorization', token);
config.headers = headers;
}
return config;
}
onRequestError(error: AxiosError): Promise<never> {
return Promise.reject(error);
}
}
注册拦截器
// 在 EntryAbility 中注册
const httpClient = new AxiosHttpClient(NetConf);
httpClient.addInterceptor(new LogInterceptor());
httpClient.addInterceptor(new AuthInterceptor());
架构模式
推荐的数据流
Server Response: {code: 1000, data: {...}, message: "success"}
↓
HttpClient 返回原始响应
↓
DataSource 创建 NetworkResult
new NetworkResult<T>(rawResponse)
↓
Repository 返回 NetworkResult<T>
↓
ViewModel 使用 RequestHelper.fromResult()
.start() .loading() .toast() .execute()
↓
得到解析后的数据 T
完整示例
1. DataSource 层
export class AuthNetworkDataSourceImpl implements AuthNetworkDataSource {
async loginByPassword(params: PasswordLoginRequest): Promise<NetworkResult<Auth>> {
const httpClient = getContainer().resolve<AxiosHttpClient>(CoreServiceKeys.HttpClient);
const rawResponse = await httpClient.post<Unknown>("user/login/password", params);
return new NetworkResult<Auth>(rawResponse);
}
}
2. Repository 层
export class AuthRepositoryImpl implements IAuthRepository {
async loginByPassword(params: PasswordLoginRequest): Promise<NetworkResult<Auth>> {
return this.networkDataSource.loginByPassword(params);
}
}
3. ViewModel 层
export class LoginViewModel extends BaseViewModel {
login(): void {
RequestHelper.fromResult<Auth>(this.authRepository.loginByPassword(params))
.start(() => this.isLoginLoading = true)
.execute()
.then((authData: Auth) => this.onLoginSuccess(authData))
.finally(() => this.isLoginLoading = false);
}
}
最佳实践
1. 统一配置管理
在 EntryAbility 中统一配置网络模块,所有 DataSource 自动获取配置。
2. 使用 NetworkResult
DataSource 层统一返回 NetworkResult<T>,保证类型安全。
3. 使用 RequestHelper.fromResult()
ViewModel 层使用 fromResult() 方法,享受链式 API 的便利。
4. 拦截器优先级
- LogInterceptor: priority = 1(最先执行)
- AuthInterceptor: priority = 10
- 其他业务拦截器: priority = 20+
文件结构
core/network/
├── Index.ets # 模块导出
├── README.md # 本文档
├── oh-package.json5 # 包配置
└── src/main/ets/
├── NetworkConfig.ets # 网络配置
├── ResponseParser.ets # 响应解析器接口
├── DefaultResponseParser.ets # 默认响应解析器
├── HttpClient.ets # HTTP 客户端接口
├── AxiosHttpClient.ets # Axios 实现
├── HttpInterceptor.ets # 拦截器接口
├── NetworkResult.ets # 响应结果封装
├── RequestHelper.ets # 请求助手
├── NetworkPageData.ets # 分页数据封装
└── NetworkPageMeta.ets # 分页元数据