🎯 empfohlene Sammlungen
Balanced sample collections from various categories for you to explore
Web TypeScript Netzwerkbeispiele
Web TypeScript Netzwerkbeispiele einschließlich HTTP-Anfragen, WebSocket-Verbindungen und API-Kommunikation
💻 Netzwerk-Utilities typescript
🟢 simple
⭐⭐
Utility-Funktionen für URL-Manipulation, Query-String-Verarbeitung, Anfragevalidierung und Netzwerkstatusüberwachung
⏱️ 20 min
🏷️ typescript, web, networking, utilities
Prerequisites:
Basic TypeScript, URL API
// Web TypeScript Network Utilities Examples
// Utility functions for common networking tasks
// 1. URL Utilities
class UrlUtilities {
// Parse URL
static parse(url: string): URL {
return new URL(url);
}
// Build URL with query parameters
static buildUrl(baseUrl: string, params: Record<string, string | number>): string {
const url = new URL(baseUrl);
Object.entries(params).forEach(([key, value]) => {
url.searchParams.set(key, String(value));
});
return url.toString();
}
// Get query parameters from URL
static getQueryParams(url: string): Record<string, string> {
const urlObj = new URL(url);
const params: Record<string, string> = {};
urlObj.searchParams.forEach((value, key) => {
params[key] = value;
});
return params;
}
// Update query parameters
static updateQueryParams(
url: string,
updates: Record<string, string | number | null>
): string {
const urlObj = new URL(url);
Object.entries(updates).forEach(([key, value]) => {
if (value === null) {
urlObj.searchParams.delete(key);
} else {
urlObj.searchParams.set(key, String(value));
}
});
return urlObj.toString();
}
// Remove query parameters
static removeQueryParams(url: string, keys: string[]): string {
const urlObj = new URL(url);
keys.forEach(key => urlObj.searchParams.delete(key));
return urlObj.toString();
}
// Check if URL is valid
static isValid(url: string): boolean {
try {
new URL(url);
return true;
} catch {
return false;
}
}
// Get domain from URL
static getDomain(url: string): string {
const urlObj = new URL(url);
return urlObj.hostname;
}
// Get path from URL
static getPath(url: string): string {
const urlObj = new URL(url);
return urlObj.pathname;
}
}
// 2. Query String Utilities
class QueryStringUtilities {
// Serialize object to query string
static stringify(obj: Record<string, any>): string {
const params = new URLSearchParams();
Object.entries(obj).forEach(([key, value]) => {
if (value !== null && value !== undefined) {
if (Array.isArray(value)) {
value.forEach(v => params.append(key, String(v)));
} else {
params.set(key, String(value));
}
}
});
return params.toString();
}
// Parse query string to object
static parse(queryString: string): Record<string, string | string[]> {
const params = new URLSearchParams(queryString);
const result: Record<string, string | string[]> = {};
params.forEach((value, key) => {
if (key in result) {
const existing = result[key];
if (Array.isArray(existing)) {
existing.push(value);
} else {
result[key] = [existing, value];
}
} else {
result[key] = value;
}
});
return result;
}
// Merge query strings
static merge(...queryStrings: string[]): string {
const mergedParams = new URLSearchParams();
queryStrings.forEach(qs => {
const params = new URLSearchParams(qs);
params.forEach((value, key) => {
mergedParams.append(key, value);
});
});
return mergedParams.toString();
}
}
// 3. Network Status Monitor
class NetworkStatusMonitor {
private isOnline: boolean = navigator.onLine;
private listeners: Array<(online: boolean) => void> = [];
constructor() {
this.setupEventListeners();
}
private setupEventListeners(): void {
window.addEventListener('online', () => {
this.isOnline = true;
this.notifyListeners(true);
});
window.addEventListener('offline', () => {
this.isOnline = false;
this.notifyListeners(false);
});
}
private notifyListeners(online: boolean): void {
this.listeners.forEach(listener => listener(online));
}
// Get current status
getStatus(): boolean {
return this.isOnline;
}
// Subscribe to status changes
subscribe(listener: (online: boolean) => void): () => void {
this.listeners.push(listener);
// Return unsubscribe function
return () => {
const index = this.listeners.indexOf(listener);
if (index > -1) {
this.listeners.splice(index, 1);
}
};
}
// Wait for connection
async waitForConnection(timeout: number = 30000): Promise<boolean> {
if (this.isOnline) {
return true;
}
return new Promise((resolve) => {
const timeoutId = setTimeout(() => {
unsubscribe();
resolve(false);
}, timeout);
const unsubscribe = this.subscribe((online) => {
if (online) {
clearTimeout(timeoutId);
unsubscribe();
resolve(true);
}
});
});
}
}
// 4. Request Validation
class RequestValidator {
// Validate URL
static validateUrl(url: string): { valid: boolean; error?: string } {
if (!url) {
return { valid: false, error: 'URL is required' };
}
try {
new URL(url);
return { valid: true };
} catch (error) {
return { valid: false, error: 'Invalid URL format' };
}
}
// Validate HTTP method
static validateMethod(method: string): { valid: boolean; error?: string } {
const validMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];
if (!validMethods.includes(method.toUpperCase())) {
return { valid: false, error: `Invalid HTTP method: ${method}` };
}
return { valid: true };
}
// Validate headers
static validateHeaders(headers: Record<string, string>): { valid: boolean; errors: string[] } {
const errors: string[] = [];
Object.entries(headers).forEach(([key, value]) => {
// Check for invalid characters in header name
if (/[^\w\-!#$%&'*+.^_`|~]/.test(key)) {
errors.push(`Invalid header name: ${key}`);
}
// Check header value
if (/[ -]/.test(value)) {
errors.push(`Invalid header value for: ${key}`);
}
});
return {
valid: errors.length === 0,
errors
};
}
// Validate request body
static validateBody(body: any, maxLength: number = 1024 * 1024): { valid: boolean; error?: string } {
const bodyString = JSON.stringify(body);
if (bodyString.length > maxLength) {
return { valid: false, error: `Request body too large (max ${maxLength} bytes)` };
}
try {
JSON.parse(bodyString);
return { valid: true };
} catch {
return { valid: false, error: 'Invalid JSON in request body' };
}
}
}
// 5. CORS Utilities
class CorsUtilities {
// Check if CORS is needed
static isCrossOrigin(url: string): boolean {
const targetOrigin = new URL(url).origin;
const currentOrigin = window.location.origin;
return targetOrigin !== currentOrigin;
}
// Build CORS request
static buildCorsRequest(url: string, options: RequestInit = {}): RequestInit {
return {
...options,
mode: 'cors',
headers: {
...(options.headers || {}),
'Content-Type': 'application/json'
}
};
}
// Check if preflight request is needed
static isPreflightRequired(method: string, headers?: Record<string, string>): boolean {
const nonSimpleMethods = ['PUT', 'DELETE', 'PATCH', 'CONNECT', 'TRACE', 'OPTIONS'];
if (nonSimpleMethods.includes(method.toUpperCase())) {
return true;
}
if (headers) {
const nonSimpleHeaders = ['X-Requested-With', 'X-HTTP-Method-Override'];
return Object.keys(headers).some(h =>
nonSimpleHeaders.some(nsh => h.toLowerCase().startsWith(nsh.toLowerCase()))
);
}
return false;
}
}
// 6. Request Retry Logic
class RequestRetryHandler {
// Retry with exponential backoff
static async retryWithBackoff<T>(
fn: () => Promise<T>,
maxRetries: number = 3,
baseDelay: number = 1000
): Promise<T> {
let lastError: Error;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error as Error;
if (attempt < maxRetries) {
const delay = baseDelay * Math.pow(2, attempt);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
throw lastError!;
}
// Retry on specific status codes
static async retryOnStatus<T>(
fn: () => Promise<Response>,
retryStatuses: number[] = [408, 429, 500, 502, 503, 504],
maxRetries: number = 3
): Promise<Response> {
let lastResponse: Response;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const response = await fn();
lastResponse = response;
if (!retryStatuses.includes(response.status)) {
return response;
}
if (attempt < maxRetries) {
await new Promise(resolve => setTimeout(resolve, 1000 * (attempt + 1)));
}
}
return lastResponse!;
}
}
// 7. Connection Pool Manager (for managing multiple concurrent requests)
class ConnectionPool {
private activeRequests: Set<Promise<any>> = new Set();
private maxConcurrent: number;
constructor(maxConcurrent: number = 6) {
this.maxConcurrent = maxConcurrent;
}
// Execute request with pool management
async execute<T>(fn: () => Promise<T>): Promise<T> {
// Wait if pool is full
while (this.activeRequests.size >= this.maxConcurrent) {
await Promise.race(this.activeRequests);
}
const request = fn().finally(() => {
this.activeRequests.delete(request);
});
this.activeRequests.add(request);
return request;
}
// Get pool size
get size(): number {
return this.activeRequests.size;
}
// Get available slots
get available(): number {
return this.maxConcurrent - this.activeRequests.size;
}
}
// 8. Network Request Logger
class NetworkRequestLogger {
private logs: Array<{
timestamp: number;
url: string;
method: string;
status?: number;
duration: number;
success: boolean;
}> = [];
// Log request
async logRequest<T>(
fn: () => Promise<T>,
url: string,
method: string = 'GET'
): Promise<T> {
const startTime = Date.now();
const timestamp = startTime;
try {
const result = await fn();
const duration = Date.now() - startTime;
this.logs.push({
timestamp,
url,
method,
status: 200,
duration,
success: true
});
return result;
} catch (error) {
const duration = Date.now() - startTime;
this.logs.push({
timestamp,
url,
method,
status: 0,
duration,
success: false
});
throw error;
}
}
// Get all logs
getLogs(): typeof this.logs {
return [...this.logs];
}
// Get failed requests
getFailedRequests(): typeof this.logs {
return this.logs.filter(log => !log.success);
}
// Get slow requests (above threshold)
getSlowRequests(threshold: number = 1000): typeof this.logs {
return this.logs.filter(log => log.duration > threshold);
}
// Get statistics
getStats(): {
total: number;
successful: number;
failed: number;
avgDuration: number;
slowest: number;
fastest: number;
} {
const successful = this.logs.filter(l => l.success).length;
const failed = this.logs.filter(l => !l.success).length;
const durations = this.logs.map(l => l.duration);
return {
total: this.logs.length,
successful,
failed,
avgDuration: durations.length ? durations.reduce((a, b) => a + b) / durations.length : 0,
slowest: durations.length ? Math.max(...durations) : 0,
fastest: durations.length ? Math.min(...durations) : 0
};
}
// Clear logs
clearLogs(): void {
this.logs = [];
}
}
// Usage Examples
async function demonstrateNetworkUtilities() {
console.log('=== Web TypeScript Network Utilities Examples ===\n');
// 1. URL utilities
console.log('--- 1. URL Utilities ---');
const url = 'https://example.com/api/users?page=1&limit=10';
console.log(`Parsed URL:`, UrlUtilities.parse(url));
console.log(`Domain:`, UrlUtilities.getDomain(url));
console.log(`Path:`, UrlUtilities.getPath(url));
console.log(`Query params:`, UrlUtilities.getQueryParams(url));
const updatedUrl = UrlUtilities.updateQueryParams(url, { page: 2, filter: 'active' });
console.log(`Updated URL:`, updatedUrl);
// 2. Query string utilities
console.log('\n--- 2. Query String Utilities ---');
const obj = { search: 'test', page: 1, filters: ['a', 'b'] };
const queryString = QueryStringUtilities.stringify(obj);
console.log(`Stringified:`, queryString);
const parsed = QueryStringUtilities.parse(queryString);
console.log(`Parsed:`, parsed);
// 3. Network status
console.log('\n--- 3. Network Status ---');
const monitor = new NetworkStatusMonitor();
console.log(`Currently online: ${monitor.getStatus()}`);
const unsubscribe = monitor.subscribe((online) => {
console.log(`Network status changed: ${online ? 'online' : 'offline'}`);
});
console.log('Subscribed to network status changes');
// 4. Request validation
console.log('\n--- 4. Request Validation ---');
const urlValidation = RequestValidator.validateUrl('https://example.com');
console.log(`URL valid: ${urlValidation.valid}`);
const methodValidation = RequestValidator.validateMethod('GET');
console.log(`Method valid: ${methodValidation.valid}`);
const headersValidation = RequestValidator.validateHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer token123'
});
console.log(`Headers valid: ${headersValidation.valid}`);
// 5. CORS utilities
console.log('\n--- 5. CORS Utilities ---');
const crossOrigin = CorsUtilities.isCrossOrigin('https://api.example.com/data');
console.log(`Is cross-origin: ${crossOrigin}`);
const needsPreflight = CorsUtilities.isPreflightRequired('PUT', { 'X-Custom-Header': 'value' });
console.log(`Needs preflight: ${needsPreflight}`);
// 6. Request retry
console.log('\n--- 6. Request Retry ---');
let attempts = 0;
const result = await RequestRetryHandler.retryWithBackoff(async () => {
attempts++;
console.log(`Attempt ${attempts}`);
if (attempts < 2) {
throw new Error('Temporary failure');
}
return 'Success!';
}, 3, 100);
console.log(`Retry result: ${result}`);
// 7. Connection pool
console.log('\n--- 7. Connection Pool ---');
const pool = new ConnectionPool(3);
const poolPromises = Array.from({ length: 5 }, (_, i) =>
pool.execute(async () => {
console.log(`Request ${i + 1} started (pool size: ${pool.size})`);
await new Promise(resolve => setTimeout(resolve, 100));
console.log(`Request ${i + 1} completed`);
return i;
})
);
await Promise.all(poolPromises);
// 8. Request logger
console.log('\n--- 8. Request Logger ---');
const logger = new NetworkRequestLogger();
await logger.logRequest(
async () => {
await new Promise(resolve => setTimeout(resolve, 50));
return 'data';
},
'https://api.example.com/data',
'GET'
);
const stats = logger.getStats();
console.log(`Logger stats:`, stats);
console.log('\n=== All Network Utilities Examples Completed ===');
}
// Export classes
export { UrlUtilities, QueryStringUtilities, NetworkStatusMonitor, RequestValidator, CorsUtilities, RequestRetryHandler, ConnectionPool, NetworkRequestLogger };
export { demonstrateNetworkUtilities };
💻 HTTP-Anfragen typescript
🟡 intermediate
⭐⭐⭐
GET, POST, PUT, DELETE-Anfragen mit Fetch API senden, mit Fehlerbehandlung und Antwortanalyse
⏱️ 25 min
🏷️ typescript, web, networking, http
Prerequisites:
Intermediate TypeScript, Fetch API
// Web TypeScript HTTP Requests Examples
// Using Fetch API for HTTP communication with servers
// 1. Basic HTTP Request Methods
class HttpClient {
private baseURL: string;
private defaultHeaders: Record<string, string>;
constructor(baseURL: string = '', defaultHeaders: Record<string, string> = {}) {
this.baseURL = baseURL;
this.defaultHeaders = {
'Content-Type': 'application/json',
...defaultHeaders
};
}
// GET request
async get<T>(url: string, headers?: Record<string, string>): Promise<T> {
const response = await fetch(`${this.baseURL}${url}`, {
method: 'GET',
headers: { ...this.defaultHeaders, ...headers }
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
// POST request
async post<T>(url: string, data: any, headers?: Record<string, string>): Promise<T> {
const response = await fetch(`${this.baseURL}${url}`, {
method: 'POST',
headers: { ...this.defaultHeaders, ...headers },
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
// PUT request
async put<T>(url: string, data: any, headers?: Record<string, string>): Promise<T> {
const response = await fetch(`${this.baseURL}${url}`, {
method: 'PUT',
headers: { ...this.defaultHeaders, ...headers },
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
// DELETE request
async delete<T>(url: string, headers?: Record<string, string>): Promise<T> {
const response = await fetch(`${this.baseURL}${url}`, {
method: 'DELETE',
headers: { ...this.defaultHeaders, ...headers }
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
// PATCH request
async patch<T>(url: string, data: any, headers?: Record<string, string>): Promise<T> {
const response = await fetch(`${this.baseURL}${url}`, {
method: 'PATCH',
headers: { ...this.defaultHeaders, ...headers },
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
}
// 2. Advanced HTTP Features
class AdvancedHttpClient {
// Request with query parameters
async getWithQueryParams<T>(
url: string,
params: Record<string, string | number>
): Promise<T> {
const queryString = new URLSearchParams(
Object.entries(params).map(([k, v]) => [k, String(v)])
).toString();
const response = await fetch(`${url}?${queryString}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
// Request with timeout
async fetchWithTimeout<T>(
url: string,
options: RequestInit = {},
timeout: number = 5000
): Promise<T> {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, {
...options,
signal: controller.signal
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
} finally {
clearTimeout(timeoutId);
}
}
// Upload file with progress
async uploadFile(
url: string,
file: File,
onProgress?: (progress: number) => void
): Promise<Response> {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', (e) => {
if (e.lengthComputable && onProgress) {
const progress = Math.round((e.loaded / e.total) * 100);
onProgress(progress);
}
});
xhr.addEventListener('load', () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(new Response(xhr.responseText, { status: xhr.status }));
} else {
reject(new Error(`HTTP error! status: ${xhr.status}`));
}
});
xhr.addEventListener('error', () => {
reject(new Error('Network error'));
});
xhr.open('POST', url);
xhr.send(file);
});
}
// Download file
async downloadFile(url: string, fileName: string): Promise<void> {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const blob = await response.blob();
const blobUrl = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = blobUrl;
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(blobUrl);
}
// Request with retry
async fetchWithRetry<T>(
url: string,
options: RequestInit = {},
maxRetries: number = 3,
delayMs: number = 1000
): Promise<T> {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
} catch (error) {
if (attempt === maxRetries) {
throw error;
}
await new Promise(resolve => setTimeout(resolve, delayMs * attempt));
}
}
throw new Error('Max retries exceeded');
}
}
// 3. Request/Response Interceptors
class HttpClientWithInterceptors {
private requestInterceptors: Array<(config: RequestInit) => RequestInit> = [];
private responseInterceptors: Array<(response: Response) => Promise<Response>> = [];
// Add request interceptor
addRequestInterceptor(interceptor: (config: RequestInit) => RequestInit): void {
this.requestInterceptors.push(interceptor);
}
// Add response interceptor
addResponseInterceptor(interceptor: (response: Response) => Promise<Response>): void {
this.responseInterceptors.push(interceptor);
}
// Execute request with interceptors
async fetchWithInterceptors(url: string, options: RequestInit = {}): Promise<Response> {
let config = options;
// Apply request interceptors
for (const interceptor of this.requestInterceptors) {
config = interceptor(config);
}
let response = await fetch(url, config);
// Apply response interceptors
for (const interceptor of this.responseInterceptors) {
response = await interceptor(response);
}
return response;
}
}
// 4. API Client Builder
class ApiClientBuilder {
private baseURL: string = '';
private headers: Record<string, string> = {};
private interceptors: {
request: Array<(config: RequestInit) => RequestInit>;
response: Array<(response: Response) => Promise<Response>>;
} = { request: [], response: [] };
setBaseURL(url: string): this {
this.baseURL = url;
return this;
}
setHeader(key: string, value: string): this {
this.headers[key] = value;
return this;
}
setHeaders(headers: Record<string, string>): this {
this.headers = { ...this.headers, ...headers };
return this;
}
addRequestInterceptor(interceptor: (config: RequestInit) => RequestInit): this {
this.interceptors.request.push(interceptor);
return this;
}
addResponseInterceptor(interceptor: (response: Response) => Promise<Response>): this {
this.interceptors.response.push(interceptor);
return this;
}
build(): HttpClient {
const client = new HttpClient(this.baseURL, this.headers);
// Apply interceptors to client if needed
// This is a simplified version
return client;
}
}
// 5. REST API Client
class RestClient {
private client: HttpClient;
constructor(baseURL: string, authToken?: string) {
const headers: Record<string, string> = {};
if (authToken) {
headers['Authorization'] = `Bearer ${authToken}`;
}
this.client = new HttpClient(baseURL, headers);
}
// CRUD operations
async getAll<T>(resource: string): Promise<T[]> {
return this.client.get<T[]>(`/${resource}`);
}
async getById<T>(resource: string, id: string | number): Promise<T> {
return this.client.get<T>(`/${resource}/${id}`);
}
async create<T>(resource: string, data: any): Promise<T> {
return this.client.post<T>(`/${resource}`, data);
}
async update<T>(resource: string, id: string | number, data: any): Promise<T> {
return this.client.put<T>(`/${resource}/${id}`, data);
}
async patch<T>(resource: string, id: string | number, data: any): Promise<T> {
return this.client.patch<T>(`/${resource}/${id}`, data);
}
async delete<T>(resource: string, id: string | number): Promise<T> {
return this.client.delete<T>(`/${resource}/${id}`);
}
// Query operations
async query<T>(resource: string, params: Record<string, any>): Promise<T[]> {
const advancedClient = new AdvancedHttpClient();
return advancedClient.getWithQueryParams<T[]>(`${this.client['baseURL']}/${resource}`, params);
}
}
// 6. GraphQL Client
class GraphQLClient {
private endpoint: string;
private headers: Record<string, string>;
constructor(endpoint: string, headers: Record<string, string> = {}) {
this.endpoint = endpoint;
this.headers = {
'Content-Type': 'application/json',
...headers
};
}
async query<T>(query: string, variables?: Record<string, any>): Promise<T> {
const response = await fetch(this.endpoint, {
method: 'POST',
headers: this.headers,
body: JSON.stringify({
query,
variables
})
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
if (result.errors) {
throw new Error(result.errors[0].message);
}
return result.data;
}
async mutate<T>(mutation: string, variables?: Record<string, any>): Promise<T> {
return this.query<T>(mutation, variables);
}
}
// 7. Response Caching
class CachedHttpClient {
private cache = new Map<string, { data: any; timestamp: number }>();
private cacheTimeout: number;
constructor(cacheTimeout: number = 60000) {
this.cacheTimeout = cacheTimeout;
}
async get<T>(url: string, useCache: boolean = true): Promise<T> {
if (useCache && this.cache.has(url)) {
const cached = this.cache.get(url)!;
const age = Date.now() - cached.timestamp;
if (age < this.cacheTimeout) {
return cached.data as T;
}
}
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
this.cache.set(url, { data, timestamp: Date.now() });
return data as T;
}
clearCache(): void {
this.cache.clear();
}
clearCacheEntry(url: string): void {
this.cache.delete(url);
}
}
// 8. Batch Requests
class BatchRequestClient {
// Execute multiple requests concurrently
async fetchAll<T>(requests: Array<{ url: string; options?: RequestInit }>): Promise<T[]> {
const promises = requests.map(req => fetch(req.url, req.options));
const responses = await Promise.all(promises);
const results: T[] = [];
for (const response of responses) {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
results.push(await response.json());
}
return results;
}
// Execute requests in batches
async fetchInBatches<T>(
requests: Array<{ url: string; options?: RequestInit }>,
batchSize: number = 5
): Promise<T[]> {
const results: T[] = [];
for (let i = 0; i < requests.length; i += batchSize) {
const batch = requests.slice(i, i + batchSize);
const batchResults = await this.fetchAll<T>(batch);
results.push(...batchResults);
}
return results;
}
}
// Usage Examples
async function demonstrateHttpRequests() {
console.log('=== Web TypeScript HTTP Requests Examples ===\n');
// 1. Basic HTTP methods
console.log('--- 1. Basic HTTP Methods ---');
const client = new HttpClient('https://jsonplaceholder.typicode.com');
try {
const posts = await client.get('/posts');
console.log(`GET /posts: Retrieved ${(posts as any).length} posts`);
const newPost = await client.post('/posts', {
title: 'Test Post',
body: 'This is a test post',
userId: 1
});
console.log(`POST /posts: Created post with ID ${(newPost as any).id}`);
} catch (error) {
console.error(`Error: ${(error as Error).message}`);
}
// 2. Query parameters
console.log('\n--- 2. Query Parameters ---');
const advancedClient = new AdvancedHttpClient();
try {
const filteredPosts = await advancedClient.getWithQueryParams(
'https://jsonplaceholder.typicode.com/posts',
{ userId: 1, _limit: 5 }
);
console.log(`Filtered posts: ${(filteredPosts as any).length} results`);
} catch (error) {
console.error(`Error: ${(error as Error).message}`);
}
// 3. Request with timeout
console.log('\n--- 3. Request with Timeout ---');
try {
const result = await advancedClient.fetchWithTimeout(
'https://jsonplaceholder.typicode.com/posts/1',
{},
3000
);
console.log(`Request completed: ${JSON.stringify(result).substring(0, 100)}...`);
} catch (error) {
console.error(`Error: ${(error as Error).message}`);
}
// 4. REST API client
console.log('\n--- 4. REST API Client ---');
const restClient = new RestClient('https://jsonplaceholder.typicode.com');
try {
const todos = await restClient.getAll('todos');
console.log(`GET /todos: ${todos.length} items`);
const todo = await restClient.getById('todos', 1);
console.log(`GET /todos/1: ${todo.title}`);
const newTodo = await restClient.create('todos', {
title: 'New Todo',
completed: false
});
console.log(`POST /todos: Created ID ${newTodo.id}`);
} catch (error) {
console.error(`Error: ${(error as Error).message}`);
}
// 5. GraphQL query
console.log('\n--- 5. GraphQL Query ---');
const graphqlClient = new GraphQLClient('https://api.github.com/graphql', {
Authorization: 'Bearer YOUR_TOKEN'
});
const query = `
query {
viewer {
login
name
}
}
`;
console.log('GraphQL query prepared (requires auth token)');
// 6. Cached requests
console.log('\n--- 6. Cached Requests ---');
const cachedClient = new CachedHttpClient(60000);
try {
const start1 = Date.now();
await cachedClient.get('https://jsonplaceholder.typicode.com/users');
const time1 = Date.now() - start1;
const start2 = Date.now();
await cachedClient.get('https://jsonplaceholder.typicode.com/users');
const time2 = Date.now() - start2;
console.log(`First request: ${time1}ms`);
console.log(`Cached request: ${time2}ms`);
} catch (error) {
console.error(`Error: ${(error as Error).message}`);
}
// 7. Batch requests
console.log('\n--- 7. Batch Requests ---');
const batchClient = new BatchRequestClient();
try {
const batchResults = await batchClient.fetchAll([
{ url: 'https://jsonplaceholder.typicode.com/posts/1' },
{ url: 'https://jsonplaceholder.typicode.com/posts/2' },
{ url: 'https://jsonplaceholder.typicode.com/posts/3' }
]);
console.log(`Batch request completed: ${batchResults.length} results`);
} catch (error) {
console.error(`Error: ${(error as Error).message}`);
}
console.log('\n=== All HTTP Requests Examples Completed ===');
}
// Export classes
export { HttpClient, AdvancedHttpClient, HttpClientWithInterceptors, ApiClientBuilder, RestClient, GraphQLClient, CachedHttpClient, BatchRequestClient };
export { demonstrateHttpRequests };
💻 WebSocket-Kommunikation typescript
🟡 intermediate
⭐⭐⭐
Echte bidirektionale Kommunikation mit WebSocket API herstellen, mit Wiederverbindung und Nachrichtenverarbeitung
⏱️ 30 min
🏷️ typescript, web, networking, websocket
Prerequisites:
Intermediate TypeScript, WebSocket API
// Web TypeScript WebSocket Communication Examples
// Real-time bidirectional communication using WebSocket API
// 1. Basic WebSocket Connection
class WebSocketClient {
private ws: WebSocket | null = null;
private url: string;
private reconnectAttempts: number = 0;
private maxReconnectAttempts: number = 5;
private reconnectDelay: number = 1000;
constructor(url: string) {
this.url = url;
}
// Connect to WebSocket server
connect(): Promise<void> {
return new Promise((resolve, reject) => {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => {
console.log('WebSocket connected');
this.reconnectAttempts = 0;
resolve();
};
this.ws.onerror = (error) => {
console.error('WebSocket error:', error);
reject(error);
};
this.ws.onclose = () => {
console.log('WebSocket disconnected');
this.attemptReconnect();
};
});
}
// Send message
send(data: string | object): void {
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
throw new Error('WebSocket is not connected');
}
const message = typeof data === 'string' ? data : JSON.stringify(data);
this.ws.send(message);
}
// Receive message
onMessage(callback: (data: any) => void): void {
if (!this.ws) {
throw new Error('WebSocket is not initialized');
}
this.ws.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
callback(data);
} catch {
callback(event.data);
}
};
}
// Close connection
close(): void {
if (this.ws) {
this.ws.close();
this.ws = null;
}
}
// Attempt to reconnect
private attemptReconnect(): void {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
const delay = this.reconnectDelay * this.reconnectAttempts;
console.log(`Reconnecting in ${delay}ms... (attempt ${this.reconnectAttempts})`);
setTimeout(() => {
this.connect();
}, delay);
} else {
console.error('Max reconnection attempts reached');
}
}
// Get connection state
get readyState(): number {
return this.ws?.readyState ?? WebSocket.CLOSED;
}
}
// 2. Advanced WebSocket with Message Queuing
class AdvancedWebSocketClient {
private ws: WebSocket | null = null;
private messageQueue: Array<string | object> = [];
private isManuallyClosed: boolean = false;
private messageHandlers: Map<string, Array<(data: any) => void>> = new Map();
private reconnectTimeout: number = 5000;
private pingInterval: NodeJS.Timeout | null = null;
constructor(private url: string) {}
// Connect with automatic reconnection
async connect(): Promise<void> {
return new Promise((resolve, reject) => {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => {
console.log('WebSocket connected');
this.startPing();
this.flushMessageQueue();
resolve();
};
this.ws.onmessage = (event) => {
this.handleMessage(event);
};
this.ws.onerror = (error) => {
console.error('WebSocket error:', error);
reject(error);
};
this.ws.onclose = () => {
console.log('WebSocket disconnected');
this.stopPing();
if (!this.isManuallyClosed) {
setTimeout(() => this.connect(), this.reconnectTimeout);
}
};
});
}
// Send message immediately or queue it
send(data: string | object, type?: string): void {
const message = type ? { type, data } : data;
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(message));
} else {
this.messageQueue.push(message);
console.log('Message queued');
}
}
// Flush queued messages
private flushMessageQueue(): void {
while (this.messageQueue.length > 0 && this.ws?.readyState === WebSocket.OPEN) {
const message = this.messageQueue.shift();
this.ws.send(JSON.stringify(message));
}
}
// Handle incoming message
private handleMessage(event: MessageEvent): void {
try {
const message = JSON.parse(event.data);
if (message.type && this.messageHandlers.has(message.type)) {
const handlers = this.messageHandlers.get(message.type)!;
handlers.forEach(handler => handler(message.data));
}
} catch (error) {
console.error('Failed to parse message:', error);
}
}
// Register message handler
on(type: string, callback: (data: any) => void): void {
if (!this.messageHandlers.has(type)) {
this.messageHandlers.set(type, []);
}
this.messageHandlers.get(type)!.push(callback);
}
// Remove message handler
off(type: string, callback: (data: any) => void): void {
const handlers = this.messageHandlers.get(type);
if (handlers) {
const index = handlers.indexOf(callback);
if (index > -1) {
handlers.splice(index, 1);
}
}
}
// Start ping to keep connection alive
private startPing(): void {
this.pingInterval = setInterval(() => {
this.send({ type: 'ping', timestamp: Date.now() });
}, 30000);
}
// Stop ping
private stopPing(): void {
if (this.pingInterval) {
clearInterval(this.pingInterval);
this.pingInterval = null;
}
}
// Close connection
close(): void {
this.isManuallyClosed = true;
this.stopPing();
if (this.ws) {
this.ws.close();
this.ws = null;
}
}
}
// 3. WebSocket Room/Channel Management
class WebSocketRoomClient {
private client: AdvancedWebSocketClient;
private currentRooms: Set<string> = new Set();
constructor(url: string) {
this.client = new AdvancedWebSocketClient(url);
}
// Connect to server
async connect(): Promise<void> {
await this.client.connect();
}
// Join room
joinRoom(roomName: string): void {
if (!this.currentRooms.has(roomName)) {
this.client.send({ type: 'join', room: roomName });
this.currentRooms.add(roomName);
console.log(`Joined room: ${roomName}`);
}
}
// Leave room
leaveRoom(roomName: string): void {
if (this.currentRooms.has(roomName)) {
this.client.send({ type: 'leave', room: roomName });
this.currentRooms.delete(roomName);
console.log(`Left room: ${roomName}`);
}
}
// Send message to room
sendToRoom(roomName: string, message: any): void {
this.client.send({
type: 'room_message',
room: roomName,
data: message
});
}
// Listen to room messages
onRoomMessage(roomName: string, callback: (message: any) => void): void {
this.client.on('room_message', (data) => {
if (data.room === roomName) {
callback(data.message);
}
});
}
// Leave all rooms
leaveAllRooms(): void {
this.currentRooms.forEach(room => this.leaveRoom(room));
}
// Close connection
close(): void {
this.leaveAllRooms();
this.client.close();
}
}
// 4. WebSocket with Authentication
class AuthenticatedWebSocketClient {
private ws: WebSocket | null = null;
private authToken: string;
private reconnectOnAuthFailure: boolean = true;
constructor(
private url: string,
authToken: string
) {
this.authToken = authToken;
}
// Connect with authentication
async connect(): Promise<void> {
const wsUrl = `${this.url}?token=${this.authToken}`;
return new Promise((resolve, reject) => {
this.ws = new WebSocket(wsUrl);
this.ws.onopen = () => {
console.log('Authenticated WebSocket connected');
resolve();
};
this.ws.onmessage = (event) => {
const message = JSON.parse(event.data);
// Handle authentication failure
if (message.type === 'auth_error') {
console.error('Authentication failed:', message.error);
if (this.reconnectOnAuthFailure) {
// Could trigger token refresh here
}
reject(new Error(message.error));
}
};
this.ws.onerror = (error) => {
console.error('WebSocket error:', error);
reject(error);
};
this.ws.onclose = (event) => {
console.log(`WebSocket closed: ${event.code}`);
};
});
}
// Send authenticated message
send(data: any): void {
if (this.ws?.readyState === WebSocket.OPEN) {
const message = {
...data,
token: this.authToken
};
this.ws.send(JSON.stringify(message));
}
}
// Update authentication token
updateToken(newToken: string): void {
this.authToken = newToken;
}
// Close connection
close(): void {
this.ws?.close();
}
}
// 5. Binary Data Handling
class BinaryWebSocketClient {
private ws: WebSocket | null = null;
constructor(private url: string) {}
// Connect
async connect(binaryType: BinaryType = 'blob'): Promise<void> {
return new Promise((resolve, reject) => {
this.ws = new WebSocket(this.url);
this.ws.binaryType = binaryType;
this.ws.onopen = () => resolve();
this.ws.onerror = reject;
});
}
// Send binary data
sendBinary(data: ArrayBuffer | Blob): void {
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send(data);
}
}
// Receive binary data
onBinaryData(callback: (data: ArrayBuffer | Blob) => void): void {
if (this.ws) {
this.ws.onmessage = (event) => {
callback(event.data);
};
}
}
// Close connection
close(): void {
this.ws?.close();
}
}
// 6. WebSocket RPC (Remote Procedure Call)
class WebSocketRPCClient {
private requestCallbacks: Map<number, (response: any) => void> = new Map();
private requestId: number = 0;
private client: AdvancedWebSocketClient;
constructor(url: string) {
this.client = new AdvancedWebSocketClient(url);
}
// Connect
async connect(): Promise<void> {
await this.client.connect();
// Listen for RPC responses
this.client.on('rpc_response', (data) => {
const { id, result, error } = data;
const callback = this.requestCallbacks.get(id);
if (callback) {
callback({ result, error });
this.requestCallbacks.delete(id);
}
});
}
// Call remote method
async call(method: string, params?: any): Promise<any> {
const id = ++this.requestId;
return new Promise((resolve, reject) => {
this.requestCallbacks.set(id, ({ result, error }) => {
if (error) {
reject(new Error(error));
} else {
resolve(result);
}
});
this.client.send({
type: 'rpc_request',
id,
method,
params
});
});
}
// Register remote method handler
on(method: string, handler: (params: any) => any): void {
this.client.on('rpc_request', async (data) => {
if (data.method === method) {
try {
const result = await handler(data.params);
this.client.send({
type: 'rpc_response',
id: data.id,
result
});
} catch (error) {
this.client.send({
type: 'rpc_response',
id: data.id,
error: (error as Error).message
});
}
}
});
}
// Close connection
close(): void {
this.client.close();
}
}
// 7. WebSocket Statistics and Monitoring
class MonitoredWebSocketClient {
private client: WebSocketClient;
private stats = {
messagesSent: 0,
messagesReceived: 0,
bytesSent: 0,
bytesReceived: 0,
connectionTime: 0,
reconnectionCount: 0
};
constructor(url: string) {
this.client = new WebSocketClient(url);
}
// Connect with monitoring
async connect(): Promise<void> {
this.stats.connectionTime = Date.now();
await this.client.connect();
// Wrap message handler to monitor
this.client.onMessage((data) => {
this.stats.messagesReceived++;
this.stats.bytesReceived += JSON.stringify(data).length;
});
}
// Send with monitoring
send(data: any): void {
const message = JSON.stringify(data);
this.stats.messagesSent++;
this.stats.bytesSent += message.length;
this.client.send(data);
}
// Get statistics
getStats(): typeof this.stats {
return {
...this.stats,
uptime: Date.now() - this.stats.connectionTime
};
}
// Print statistics
printStats(): void {
const stats = this.getStats();
console.log('\n=== WebSocket Statistics ===');
console.log(`Messages Sent: ${stats.messagesSent}`);
console.log(`Messages Received: ${stats.messagesReceived}`);
console.log(`Bytes Sent: ${stats.bytesSent}`);
console.log(`Bytes Received: ${stats.bytesReceived}`);
console.log(`Uptime: ${stats.uptime}ms`);
}
// Close connection
close(): void {
this.client.close();
}
}
// Usage Examples
async function demonstrateWebSocket() {
console.log('=== Web TypeScript WebSocket Examples ===\n');
// Note: These examples require a WebSocket server to connect to
// Replace 'ws://localhost:8080' with your WebSocket server URL
// 1. Basic WebSocket
console.log('--- 1. Basic WebSocket Connection ---');
const basicClient = new WebSocketClient('ws://localhost:8080');
try {
// Uncomment to test with actual server
// await basicClient.connect();
// basicClient.send({ type: 'greeting', message: 'Hello Server!' });
// basicClient.onMessage((data) => console.log('Received:', data));
console.log('Basic WebSocket client created (requires server)');
} catch (error) {
console.error(`Error: ${(error as Error).message}`);
}
// 2. Advanced WebSocket with message handlers
console.log('\n--- 2. Advanced WebSocket ---');
const advancedClient = new AdvancedWebSocketClient('ws://localhost:8080');
// Register message handlers
advancedClient.on('chat', (data) => {
console.log('Chat message:', data);
});
advancedClient.on('notification', (data) => {
console.log('Notification:', data);
});
console.log('Advanced WebSocket client with handlers created');
// 3. Room management
console.log('\n--- 3. Room Management ---');
const roomClient = new WebSocketRoomClient('ws://localhost:8080');
// Uncomment to test with actual server
// await roomClient.connect();
// roomClient.joinRoom('general');
// roomClient.sendToRoom('general', { text: 'Hello everyone!' });
// roomClient.onRoomMessage('general', (msg) => console.log('Room message:', msg));
console.log('Room client created');
// 4. Authenticated WebSocket
console.log('\n--- 4. Authenticated WebSocket ---');
const authClient = new AuthenticatedWebSocketClient(
'ws://localhost:8080',
'your-auth-token'
);
console.log('Authenticated WebSocket client created');
// 5. RPC client
console.log('\n--- 5. WebSocket RPC ---');
const rpcClient = new WebSocketRPCClient('ws://localhost:8080');
// Uncomment to test with actual server
// await rpcClient.connect();
// const result = await rpcClient.call('add', { a: 5, b: 3 });
// console.log('RPC result:', result);
console.log('RPC client created');
// 6. Monitoring
console.log('\n--- 6. WebSocket Monitoring ---');
const monitoredClient = new MonitoredWebSocketClient('ws://localhost:8080');
console.log('Monitored WebSocket client created');
console.log('\n=== All WebSocket Examples Completed ===');
console.log('Note: These examples require a WebSocket server to connect to');
}
// Export classes
export { WebSocketClient, AdvancedWebSocketClient, WebSocketRoomClient, AuthenticatedWebSocketClient, BinaryWebSocketClient, WebSocketRPCClient, MonitoredWebSocketClient };
export { demonstrateWebSocket };