HTTP-Client in TypeScript: Anfragen richtig stellen von A bis Z

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

HTTP-Client in TypeScript: Anfragen richtig stellen von A bis Z

\n\n

Moderne Webentwicklung ist ohne Interaktion mit entfernten Servern undenkbar. Ob das Abrufen von Daten von einer REST-API, das Senden von Formularen oder das Hochladen von Dateien – HTTP-Anfragen sind die Grundlage der Client-Server-Architektur. TypeScript ermöglicht mit seiner strengen Typisierung und leistungsstarken Werkzeugen, die Arbeit mit HTTP-Anfragen nicht nur sicher, sondern auch wartungsfreundlich zu gestalten. In diesem Artikel werden wir uns ansehen, wie man einen durchdachten HTTP-Client in TypeScript erstellt, typische Fehler vermeidet und Code schreibt, der vorhersagbar funktioniert.

\n\n

1. Grundlagen: fetch API und ihre Typisierung

\n\n

Der in den Browser integrierte fetch ist ein modernes und flexibles Werkzeug zur Durchführung von HTTP-Anfragen. Seine Verwendung in TypeScript erfordert jedoch eine korrekte Typisierung der Antwort. Standardmäßig gibt fetch ein Promise<Response> zurück, und wir müssen explizit angeben, welche Daten wir erwarten.

\n\n
interface User {\n  id: number;\n  name: string;\n  email: string;\n}\n\nasync function getUser(id: number): Promise<User> {\n  const response = await fetch(`https://api.example.com/users/${id}`);\n  \n  if (!response.ok) {\n    throw new Error(`HTTP error! status: ${response.status}`);\n  }\n  \n  const data: User = await response.json();\n  return data;\n}\n
\n\n

Beachten Sie die Überprüfung von response.ok. Dies ist entscheidend: Selbst wenn der Server einen Fehler zurückgibt (404, 500 usw.), wirft fetch nicht automatisch eine Ausnahme. Wir müssen den Status manuell behandeln.

\n\n

Für POST-Anfragen mit einem Body muss der Header Content-Type angegeben werden:

\n\n
async function createUser(userData: Omit<User, 'id'>): Promise<User> {\n  const response = await fetch('https://api.example.com/users', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify(userData),\n  });\n\n  if (!response.ok) {\n    throw new Error(`Failed to create user: ${response.statusText}`);\n  }\n\n  return response.json();\n}\n
\n\n

2. Erstellung eines universellen HTTP-Clients

\n\n

Anstatt jedes Mal fetch von Grund auf neu zu schreiben, ist es besser, einen Wrapper zu erstellen – einen universellen HTTP-Client. Dies ermöglicht die zentrale Verwaltung der Basis-URL, Header und Fehlerbehandlung. Betrachten wir ein Beispiel auf Basis von Klassen:

\n\n
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n\ninterface RequestConfig<TBody = unknown> {\n  method: HttpMethod;\n  url: string;\n  body?: TBody;\n  headers?: Record<string, string>;\n  params?: Record<string, string>;\n}\n\nclass HttpClient {\n  private baseUrl: string;\n  private defaultHeaders: Record<string, string>;\n\n  constructor(baseUrl: string, defaultHeaders: Record<string, string> = {}) {\n    this.baseUrl = baseUrl;\n    this.defaultHeaders = {\n      'Content-Type': 'application/json',\n      ...defaultHeaders,\n    };\n  }\n\n  private async request<TResponse, TBody = unknown>(\n    config: RequestConfig<TBody>\n  ): Promise<TResponse> {\n    const url = new URL(`${this.baseUrl}${config.url}`);\n    \n    if (config.params) {\n      Object.entries(config.params).forEach(([key, value]) => {\n        url.searchParams.append(key, value);\n      });\n    }\n\n    const response = await fetch(url.toString(), {\n      method: config.method,\n      headers: { ...this.defaultHeaders, ...config.headers },\n      body: config.body ? JSON.stringify(config.body) : undefined,\n    });\n\n    if (!response.ok) {\n      const errorBody = await response.text();\n      throw new Error(`Request failed: ${response.status} ${response.statusText}. Body: ${errorBody}`);\n    }\n\n    // Für DELETE oder andere Methoden, die möglicherweise keinen Body zurückgeben\n    if (response.status === 204) {\n      return undefined as TResponse;\n    }\n\n    return response.jso                

Blogs

Buchempfehlungen