CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-rxjs

Reactive Extensions for modern JavaScript providing comprehensive reactive programming with observable sequences

Pending
Overview
Eval results
Files

ajax-operations.mddocs/

AJAX Operations

HTTP request capabilities with full observable integration, response streaming, and comprehensive error handling for web API interactions.

Capabilities

ajax Function

Core function for creating HTTP request observables.

/**
 * Create observable HTTP requests with comprehensive configuration
 * @param request - URL string or detailed configuration object
 * @returns Observable emitting AjaxResponse
 */
function ajax<T>(request: string | AjaxConfig): Observable<AjaxResponse<T>>;

/**
 * Create GET request observable returning JSON response
 * @param url - URL to request
 * @param headers - Optional request headers
 * @returns Observable emitting parsed JSON response
 */
function ajax.getJSON<T>(url: string, headers?: Record<string, any>): Observable<T>;

/**
 * Create GET request observable  
 * @param url - URL to request
 * @param headers - Optional request headers
 * @returns Observable emitting AjaxResponse
 */
function ajax.get(url: string, headers?: Record<string, any>): Observable<AjaxResponse<any>>;

/**
 * Create POST request observable
 * @param url - URL to request
 * @param body - Request body
 * @param headers - Optional request headers
 * @returns Observable emitting AjaxResponse
 */
function ajax.post(url: string, body?: any, headers?: Record<string, any>): Observable<AjaxResponse<any>>;

/**
 * Create PUT request observable
 * @param url - URL to request
 * @param body - Request body
 * @param headers - Optional request headers
 * @returns Observable emitting AjaxResponse
 */
function ajax.put(url: string, body?: any, headers?: Record<string, any>): Observable<AjaxResponse<any>>;

/**
 * Create PATCH request observable
 * @param url - URL to request
 * @param body - Request body
 * @param headers - Optional request headers
 * @returns Observable emitting AjaxResponse
 */
function ajax.patch(url: string, body?: any, headers?: Record<string, any>): Observable<AjaxResponse<any>>;

/**
 * Create DELETE request observable
 * @param url - URL to request
 * @param headers - Optional request headers
 * @returns Observable emitting AjaxResponse
 */
function ajax.delete(url: string, headers?: Record<string, any>): Observable<AjaxResponse<any>>;

Usage Examples:

import { ajax } from "rxjs/ajax";
import { map, catchError } from "rxjs/operators";
import { of } from "rxjs";

// Simple GET request
ajax.getJSON<User>('/api/users/123').subscribe(
  user => console.log('User:', user),
  err => console.error('Error:', err)
);

// GET with headers
ajax.get('/api/data', {
  'Authorization': 'Bearer token123',
  'Content-Type': 'application/json'
}).subscribe(response => {
  console.log('Status:', response.status);
  console.log('Data:', response.response);
});

// POST request
ajax.post('/api/users', {
  name: 'John Doe',
  email: 'john@example.com'
}, {
  'Content-Type': 'application/json'
}).subscribe(
  response => console.log('Created user:', response.response),
  err => console.error('Creation failed:', err)
);

// Advanced configuration
ajax({
  url: '/api/upload',
  method: 'POST',
  body: formData,
  timeout: 30000,
  responseType: 'json',
  withCredentials: true
}).subscribe(
  response => console.log('Upload successful:', response),
  err => console.error('Upload failed:', err)
);

AjaxConfig Interface

Comprehensive configuration for HTTP requests.

/**
 * Configuration object for AJAX requests
 */
interface AjaxConfig {
  /** Request URL */
  url?: string;
  
  /** HTTP method (GET, POST, PUT, DELETE, etc.) */
  method?: string;
  
  /** Request headers object */
  headers?: Record<string, any>;
  
  /** Request body (any serializable data) */
  body?: any;
  
  /** Include credentials in cross-origin requests */
  withCredentials?: boolean;
  
  /** Username for HTTP authentication */
  user?: string;
  
  /** Password for HTTP authentication */
  password?: string;
  
  /** Request timeout in milliseconds */
  timeout?: number;
  
  /** Response type expected */
  responseType?: XMLHttpRequestResponseType;
  
  /** Custom XMLHttpRequest creation function */
  createXHR?: () => XMLHttpRequest;
  
  /** Progress event handler */
  progressSubscriber?: Subscriber<any>;
  
  /** Include response headers in result */
  includeDownloadProgress?: boolean;
  
  /** Include upload progress events */
  includeUploadProgress?: boolean;
  
  /** Custom result selector function */
  resultSelector?: (response: AjaxResponse<any>) => any;
  
  /** Cross-domain request handling */
  crossDomain?: boolean;
}

/**
 * Response type values for XMLHttpRequest
 */
type XMLHttpRequestResponseType = "" | "arraybuffer" | "blob" | "document" | "json" | "text";

AjaxResponse Class

Wrapper for HTTP responses with metadata.

/**
 * Wrapper for HTTP response data and metadata
 */
class AjaxResponse<T> {
  /** Parsed response data */
  readonly response: T;
  
  /** HTTP status code */
  readonly status: number;
  
  /** HTTP status text */
  readonly responseText: string;
  
  /** Response headers */
  readonly responseHeaders: Record<string, string>;
  
  /** Original request configuration */
  readonly request: AjaxConfig;
  
  /** Response type */
  readonly responseType: XMLHttpRequestResponseType;
  
  /** Total bytes loaded */
  readonly loaded: number;
  
  /** Total bytes to load */
  readonly total: number;
  
  /** Original XMLHttpRequest object */
  readonly originalEvent: ProgressEvent;
  
  /** Original XMLHttpRequest instance */
  readonly xhr: XMLHttpRequest;
  
  constructor(
    originalEvent: Event,
    xhr: XMLHttpRequest,
    request: AjaxConfig
  );
}

Error Classes

Specialized error types for HTTP request failures.

/**
 * Error for general AJAX request failures
 */
class AjaxError extends Error {
  /** Error name */
  readonly name: "AjaxError";
  
  /** HTTP status code */
  readonly status: number;
  
  /** Response text */
  readonly responseText: string;
  
  /** Original XMLHttpRequest */
  readonly xhr: XMLHttpRequest;
  
  /** Original request configuration */
  readonly request: AjaxConfig;
  
  constructor(message: string, xhr: XMLHttpRequest, request: AjaxConfig);
}

/**
 * Error for AJAX request timeouts
 */
class AjaxTimeoutError extends AjaxError {
  /** Error name */
  readonly name: "AjaxTimeoutError";
  
  constructor(xhr: XMLHttpRequest, request: AjaxConfig);
}

Advanced AJAX Patterns

Request Interceptors

import { ajax } from "rxjs/ajax";
import { tap, catchError, retryWhen, delay, take } from "rxjs/operators";

// Create HTTP client with interceptors
class HttpClient {
  private baseURL = 'https://api.example.com';
  private authToken = '';
  
  setAuthToken(token: string) {
    this.authToken = token;
  }
  
  private createRequest(config: AjaxConfig): Observable<AjaxResponse<any>> {
    const fullConfig: AjaxConfig = {
      ...config,
      url: `${this.baseURL}${config.url}`,
      headers: {
        'Content-Type': 'application/json',
        ...(this.authToken && { 'Authorization': `Bearer ${this.authToken}` }),
        ...config.headers
      },
      timeout: 10000
    };
    
    return ajax(fullConfig).pipe(
      tap(response => {
        console.log(`${config.method} ${config.url}:`, response.status);
      }),
      retryWhen(errors => 
        errors.pipe(
          delay(1000),
          take(3) // Retry up to 3 times
        )
      ),
      catchError(err => {
        if (err instanceof AjaxTimeoutError) {
          console.error('Request timeout:', config.url);
        } else if (err instanceof AjaxError) {
          console.error(`HTTP Error ${err.status}:`, err.responseText);
        }
        throw err;
      })
    );
  }
  
  get<T>(url: string, headers?: Record<string, any>): Observable<T> {
    return this.createRequest({ url, method: 'GET', headers }).pipe(
      map(response => response.response)
    );
  }
  
  post<T>(url: string, body: any, headers?: Record<string, any>): Observable<T> {
    return this.createRequest({ 
      url, 
      method: 'POST', 
      body: JSON.stringify(body), 
      headers 
    }).pipe(
      map(response => response.response)
    );
  }
}

const httpClient = new HttpClient();
httpClient.setAuthToken('your-token-here');

// Usage
httpClient.get<User>('/users/123').subscribe(user => {
  console.log('User loaded:', user);
});

File Upload with Progress

import { ajax } from "rxjs/ajax";
import { Subject } from "rxjs";

function uploadFile(file: File, url: string): Observable<AjaxResponse<any>> {
  const formData = new FormData();
  formData.append('file', file);
  
  const progressSubject = new Subject<number>();
  
  const upload$ = ajax({
    url,
    method: 'POST',
    body: formData,
    progressSubscriber: progressSubject,
    includeUploadProgress: true
  });
  
  // Monitor progress
  progressSubject.subscribe(progress => {
    const percentage = (progress.loaded / progress.total) * 100;
    console.log(`Upload progress: ${percentage.toFixed(1)}%`);
    updateProgressBar(percentage);
  });
  
  return upload$;
}

// Usage
const fileInput = document.getElementById('file') as HTMLInputElement;
fileInput.addEventListener('change', (event) => {
  const file = event.target.files[0];
  if (file) {
    uploadFile(file, '/api/upload').subscribe(
      response => console.log('Upload complete:', response.response),
      err => console.error('Upload failed:', err)
    );
  }
});

Response Caching

import { ajax } from "rxjs/ajax";
import { shareReplay, tap } from "rxjs/operators";

class CachedHttpClient {
  private cache = new Map<string, Observable<any>>();
  
  get<T>(url: string, cacheKey?: string): Observable<T> {
    const key = cacheKey || url;
    
    if (!this.cache.has(key)) {
      const request$ = ajax.getJSON<T>(url).pipe(
        tap(data => console.log(`Cached: ${key}`)),
        shareReplay(1) // Share and replay last emission
      );
      
      this.cache.set(key, request$);
      
      // Auto-expire cache after 5 minutes
      setTimeout(() => {
        this.cache.delete(key);
        console.log(`Cache expired: ${key}`);
      }, 5 * 60 * 1000);
    }
    
    return this.cache.get(key)!;
  }
  
  clearCache(key?: string) {
    if (key) {
      this.cache.delete(key);
    } else {
      this.cache.clear();
    }
  }
}

const cachedClient = new CachedHttpClient();

// First call - makes HTTP request
cachedClient.get<User[]>('/api/users').subscribe(users => {
  console.log('Users (from server):', users);
});

// Second call - returns cached data
cachedClient.get<User[]>('/api/users').subscribe(users => {
  console.log('Users (from cache):', users);
});

Parallel Requests

import { ajax } from "rxjs/ajax";
import { forkJoin, combineLatest } from "rxjs";
import { map } from "rxjs/operators";

// Load multiple resources in parallel
const userRequest$ = ajax.getJSON<User>('/api/user/123');
const postsRequest$ = ajax.getJSON<Post[]>('/api/user/123/posts');
const commentsRequest$ = ajax.getJSON<Comment[]>('/api/user/123/comments');

// Wait for all to complete
forkJoin({
  user: userRequest$,
  posts: postsRequest$,
  comments: commentsRequest$
}).subscribe(({ user, posts, comments }) => {
  console.log('All data loaded:', { user, posts, comments });
});

// Combine latest values as they arrive
combineLatest([
  userRequest$,
  postsRequest$,
  commentsRequest$
]).pipe(
  map(([user, posts, comments]) => ({ user, posts, comments }))
).subscribe(data => {
  console.log('Combined data:', data);
});

Types

interface AjaxRequest extends AjaxConfig {
  url: string;
  method: string;
}

type AjaxDirection = "upload" | "download";

interface User {
  id: number;
  name: string;
  email: string;
}

interface Post {
  id: number;
  title: string;
  content: string;
  userId: number;
}

interface Comment {
  id: number;
  text: string;
  postId: number;
  userId: number;
}

Install with Tessl CLI

npx tessl i tessl/npm-rxjs

docs

ajax-operations.md

combination-operators.md

core-types.md

error-handling.md

fetch-operations.md

filtering-operators.md

index.md

observable-creation.md

schedulers.md

subjects.md

testing-utilities.md

transformation-operators.md

websocket-operations.md

tile.json