Skip to content

网络请求

概述

网络请求模块封装了 HTTP 请求功能,提供统一的请求接口、拦截器机制和错误处理。

核心组件

组件职责
AxiosHttpClientHTTP 客户端
NetworkConfig网络配置
RequestHelper请求辅助类
HttpInterceptor拦截器接口
NetworkResult网络结果封装

网络配置

NetworkConfig

typescript
interface NetworkConfig {
  baseUrl: string;              // API 基础地址
  timeout: number;              // 超时时间(毫秒)
  responseParser: {
    successCode: number;        // 成功状态码
    dataField: string;          // 数据字段名
    messageField: string;       // 消息字段名
    codeField: string;          // 状态码字段名
  };
  headers: Record<string, string>;  // 默认请求头
  enableLog: boolean;           // 是否启用日志
}

配置示例

typescript
const config: NetworkConfig = {
  baseUrl: "https://api.example.com/",
  timeout: 10000,
  responseParser: {
    successCode: 1000,
    dataField: 'data',
    messageField: 'message',
    codeField: 'code'
  },
  headers: {
    'Content-Type': 'application/json'
  },
  enableLog: true
};

HTTP 客户端

创建客户端

typescript
import { AxiosHttpClient, NetworkConfig } from "@core/network";

const client = new AxiosHttpClient(config);

发起请求

typescript
// GET 请求
const response = await client.get<UserInfo>("/users/123");

// POST 请求
const response = await client.post<UserInfo>("/users", {
  name: "张三",
  email: "zhangsan@example.com"
});

// PUT 请求
const response = await client.put<UserInfo>("/users/123", {
  name: "李四"
});

// DELETE 请求
const response = await client.delete("/users/123");

拦截器

拦截器接口

typescript
interface HttpInterceptor {
  onRequest(config: AxiosRequestConfig): Promise<AxiosRequestConfig>;
  onResponse(response: AxiosResponse): Promise<AxiosResponse>;
  onError(error: AxiosError): Promise<AxiosError>;
}

创建拦截器

typescript
class AuthInterceptor implements HttpInterceptor {
  async onRequest(config: AxiosRequestConfig): Promise<AxiosRequestConfig> {
    // 添加认证信息
    const token = await getToken();
    if (token) {
      config.headers = config.headers || {};
      config.headers['Authorization'] = `Bearer ${token}`;
    }
    return config;
  }

  async onResponse(response: AxiosResponse): Promise<AxiosResponse> {
    return response;
  }

  async onError(error: AxiosError): Promise<AxiosError> {
    // 处理 401 错误
    if (error.response?.status === 401) {
      // 跳转到登录页
    }
    return error;
  }
}

注册拦截器

typescript
client.addInterceptor(new AuthInterceptor());
client.addInterceptor(new LogInterceptor());

RequestHelper

简介

RequestHelper 提供了便捷的请求辅助方法,简化网络请求的使用。

使用示例

typescript
import { RequestHelper, NetworkResult } from "@core/network";

// 从 Promise 创建
RequestHelper.fromResult<UserInfo>(getUserInfo())
  .toast(true)                    // 显示错误 Toast
  .start(() => setLoading(true))  // 请求开始回调
  .execute()
  .then((data) => {
    // 请求成功
    console.log(data);
  })
  .catch(() => {
    // 请求失败
  });

NetworkResult

结果封装

typescript
interface NetworkResult<T> {
  success: boolean;
  data?: T;
  message?: string;
  code?: number;
}

创建结果

typescript
// 成功结果
const result: NetworkResult<UserInfo> = {
  success: true,
  data: userInfo,
  code: 1000
};

// 失败结果
const result: NetworkResult<UserInfo> = {
  success: false,
  message: "用户不存在",
  code: 4004
};

使用示例

在 Service 中使用

typescript
import { getContainer, CoreServiceKeys } from "@core/di";
import { AxiosHttpClient, NetworkResult } from "@core/network";

export class UserService {
  private httpClient: AxiosHttpClient;

  constructor() {
    const container = getContainer();
    this.httpClient = container.resolve<AxiosHttpClient>(CoreServiceKeys.HttpClient);
  }

  async getUserInfo(userId: string): Promise<NetworkResult<UserInfo>> {
    try {
      const response = await this.httpClient.get<UserInfo>(`/users/${userId}`);
      return {
        success: true,
        data: response.data
      };
    } catch (error) {
      return {
        success: false,
        message: error.message
      };
    }
  }
}

在 ViewModel 中使用

typescript
import { BaseNetWorkViewModel } from "@core/base";
import { NetworkResult } from "@core/network";

@ObservedV2
export class UserProfileViewModel extends BaseNetWorkViewModel<UserInfo> {
  private userService: UserService;

  constructor() {
    super();
    this.userService = new UserService();
  }

  protected requestRepository(): Promise<NetworkResult<UserInfo>> {
    return this.userService.getUserInfo("123");
  }
}

最佳实践

1. 统一错误处理

使用拦截器统一处理错误:

typescript
class ErrorInterceptor implements HttpInterceptor {
  async onError(error: AxiosError): Promise<AxiosError> {
    if (error.response) {
      switch (error.response.status) {
        case 401:
          // 未授权,跳转登录
          break;
        case 403:
          // 无权限
          break;
        case 404:
          // 资源不存在
          break;
        case 500:
          // 服务器错误
          break;
      }
    }
    return error;
  }
}

2. 请求取消

对于可能被取消的请求,使用 AbortController:

typescript
const controller = new AbortController();

client.get("/users", {
  signal: controller.signal
});

// 取消请求
controller.abort();

3. 请求重试

对于失败的请求,可以实现重试机制:

typescript
async function requestWithRetry<T>(
  request: () => Promise<T>,
  maxRetries: number = 3
): Promise<T> {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await request();
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
    }
  }
  throw new Error("Max retries exceeded");
}

注意事项

  1. 超时设置:合理设置超时时间,避免请求hang住
  2. 错误处理:始终处理网络错误
  3. 取消请求:在组件销毁时取消未完成的请求
  4. 安全性:不要在请求中包含敏感信息

下一步