TypeScript 中的 HTTP 客户端:正确发起请求
TypeScript 是 JavaScript 的严格类型化扩展,为 Web 开发增添了可靠性和代码可读性。在使用外部 API 或后端时,正确执行 HTTP 请求的能力成为关键技能。在本文中,我们将从基本原则开始,到高级错误处理和类型化模式,详细讲解如何在 TypeScript 中创建一个功能完整的 HTTP 客户端。
为什么 TypeScript 是 HTTP 客户端的理想选择?
JavaScript 提供了多种执行 HTTP 请求的方式:内置的 fetch、axios 和 node-fetch 库。然而,TypeScript 凭借静态类型化,将使用这些工具提升到了一个全新的水平。你可以预先描述请求和响应的结构,从而在编译阶段消除许多错误。假设你正在使用一个返回用户列表的 API。如果没有类型,你可能会访问一个不存在的字段,而错误只在运行时才会出现。TypeScript 解决了这个问题。
主要部分:从头创建 HTTP 客户端
1. 使用 fetch 和类型化的基本 GET 请求
我们从最简单的 GET 请求开始。在 TypeScript 中,我们可以为响应定义一个接口,并将其传递给泛型 fetch 函数。示例如下:
interface User { id: number; name: string; email: string;}
async function getUser(id: number): Promise<User> { const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data: User = await response.json(); return data;}
// 使用getUser(1) .then(user => console.log(user.name)) .catch(error => console.error('Error:', error.message));在这里,我们明确声明该函数返回 Promise<User>。如果 API 发生变化,TypeScript 编译器会提醒你类型不匹配。请注意 response.ok 检查——这是处理 HTTP 错误(404、500 等)的必要步骤。
2. 带请求体和请求头的 POST 请求
向服务器发送数据需要设置请求头并序列化请求体。让我们创建一个创建新用户的函数:
interface CreateUserRequest { name: string; email: string;}
interface CreateUserResponse { id: number; name: string; email: string;}
async function createUser(userData: CreateUserRequest): Promise<CreateUserResponse> { const response = await fetch('https://jsonplaceholder.typicode.com/users', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(userData), });
if (!response.ok) { const errorBody = await response.text(); throw new Error(`Creation error: ${response.status} - ${errorBody}`); }
return await response.json();}
// 示例调用const newUser: CreateUserRequest = { name: 'Ivan', email: 'ivan@example.com' };createUser(newUser).then(result => console.log('Created ID:', result.id));对 CreateUserRequest 和 CreateUserResponse 进行类型化使代码具有自文档性。其他开发者可以立即看到发送时需要哪些字段,以及响应中期望获得什么。
3. 带错误处理的通用 HTTP 客户端
在实际项目中,很少只靠一个函数就能解决问题。更好的方法是创建一个通用类或一组函数,将请求逻辑集中处理。以下是一个高级客户端的示例:
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
interface RequestConfig { method: HttpMethod; endpoint: string; body?: unknown; params?: Record<string, string>;}
class HttpClient { private baseUrl: string;