jQuery provides a comprehensive AJAX API for making asynchronous HTTP requests with full TypeScript support. The system includes Promise-like objects, detailed configuration options, and type-safe request/response handling.
interface JQueryStatic {
// Main AJAX method
ajax(url: string): JQuery.jqXHR;
ajax(url: string, settings: JQuery.AjaxSettings): JQuery.jqXHR;
ajax(settings: JQuery.AjaxSettings): JQuery.jqXHR;
// Convenience methods
get(url: string): JQuery.jqXHR;
get(url: string, data: JQuery.PlainObject | string): JQuery.jqXHR;
get(url: string, data: JQuery.PlainObject | string, success: JQuery.Ajax.SuccessCallback, dataType?: string): JQuery.jqXHR;
get(url: string, success: JQuery.Ajax.SuccessCallback, dataType?: string): JQuery.jqXHR;
post(url: string): JQuery.jqXHR;
post(url: string, data: JQuery.PlainObject | string): JQuery.jqXHR;
post(url: string, data: JQuery.PlainObject | string, success: JQuery.Ajax.SuccessCallback, dataType?: string): JQuery.jqXHR;
post(url: string, success: JQuery.Ajax.SuccessCallback, dataType?: string): JQuery.jqXHR;
// Specialized methods
getJSON(url: string): JQuery.jqXHR;
getJSON(url: string, data: JQuery.PlainObject | string): JQuery.jqXHR;
getJSON(url: string, data: JQuery.PlainObject | string, success: JQuery.Ajax.SuccessCallback): JQuery.jqXHR;
getJSON(url: string, success: JQuery.Ajax.SuccessCallback): JQuery.jqXHR;
getScript(url: string): JQuery.jqXHR;
getScript(url: string, success: JQuery.Ajax.SuccessCallback): JQuery.jqXHR;
// Form loading
load(url: string): JQuery.jqXHR;
load(url: string, data: JQuery.PlainObject | string): JQuery.jqXHR;
load(url: string, data: JQuery.PlainObject | string, complete: JQuery.Ajax.CompleteCallback): JQuery.jqXHR;
load(url: string, complete: JQuery.Ajax.CompleteCallback): JQuery.jqXHR;
}declare namespace JQuery.Ajax {
// Main settings interface
interface AjaxSettings<TContext = any> {
// Request configuration
url?: string;
type?: string;
method?: string;
data?: any;
contentType?: string | boolean;
dataType?: string;
headers?: JQuery.PlainObject<string>;
// Authentication and cross-origin
username?: string;
password?: string;
crossDomain?: boolean;
xhrFields?: JQuery.PlainObject;
// Timing and behavior
timeout?: number;
cache?: boolean;
async?: boolean;
processData?: boolean;
// Callbacks
beforeSend?: (this: TContext, jqXHR: JQuery.jqXHR, settings: AjaxSettings<TContext>) => false | void;
success?: SuccessCallback<TContext>;
error?: ErrorCallback<TContext>;
complete?: CompleteCallback<TContext>;
dataFilter?: (data: string, type: string) => any;
// Upload progress (if supported)
xhr?: () => XMLHttpRequest;
// Context for callbacks
context?: TContext;
// JSONP settings
jsonp?: string | boolean;
jsonpCallback?: string | (() => string);
// Status codes
statusCode?: {
[key: number]: () => void;
};
// Converters
converters?: {
[key: string]: (value: any) => any;
};
// Script and style settings
scriptCharset?: string;
scriptAttrs?: JQuery.PlainObject<string>;
}
// Callback types
type SuccessCallback<TContext = any> = (this: TContext, data: any, textStatus: TextStatus, jqXHR: JQuery.jqXHR) => void;
type ErrorCallback<TContext = any> = (this: TContext, jqXHR: JQuery.jqXHR, textStatus: TextStatus, errorThrown: string) => void;
type CompleteCallback<TContext = any> = (this: TContext, jqXHR: JQuery.jqXHR, textStatus: TextStatus) => void;
// Status types
type TextStatus = "success" | "notmodified" | "nocontent" | "error" | "timeout" | "abort" | "parsererror";
}declare namespace JQuery {
// Enhanced XMLHttpRequest object
interface jqXHR extends XMLHttpRequest, Promise<any> {
// Response properties
responseJSON?: any;
responseText: string;
responseXML?: Document;
// Request information
readyState: number;
status: number;
statusText: string;
// Promise methods
done(doneCallback: (data: any, textStatus: string, jqXHR: jqXHR) => void): jqXHR;
fail(failCallback: (jqXHR: jqXHR, textStatus: string, errorThrown: string) => void): jqXHR;
always(alwaysCallback: (dataOrjqXHR: any, textStatus: string, jqXHROrErrorThrown: jqXHR | string) => void): jqXHR;
then<TResolve = any, TReject = never>(
doneFilter?: (data: any, textStatus: string, jqXHR: jqXHR) => TResolve | PromiseLike<TResolve>,
failFilter?: (jqXHR: jqXHR, textStatus: string, errorThrown: string) => TReject | PromiseLike<TReject>
): Promise<TResolve | TReject>;
// Control methods
abort(statusText?: string): jqXHR;
// Header methods
getAllResponseHeaders(): string;
getResponseHeader(name: string): string | null;
setRequestHeader(name: string, value: string): jqXHR;
overrideMimeType(type: string): jqXHR;
// State methods
state(): string;
statusCode(map: { [key: number]: () => void }): jqXHR;
}
}// Simple GET request
$.get('/api/users')
.done(data => console.log('Users:', data))
.fail((xhr, status, error) => console.error('Error:', error));
// GET with data parameters
$.get('/api/users', { page: 1, limit: 10 })
.done(users => console.log('Page 1:', users));
// GET with success callback (legacy style)
$.get('/api/users', data => {
console.log('Users loaded:', data);
}, 'json');
// Type-safe GET request
interface User {
id: number;
name: string;
email: string;
}
$.get('/api/users').done((users: User[]) => {
users.forEach(user => {
console.log(`User: ${user.name} (${user.email})`);
});
});// Simple POST request
const userData = { name: 'John Doe', email: 'john@example.com' };
$.post('/api/users', userData)
.done(response => console.log('User created:', response))
.fail(xhr => console.error('Creation failed:', xhr.responseText));
// POST with JSON data
const postData = JSON.stringify(userData);
$.post('/api/users', postData, 'json')
.done(response => console.log('Response:', response));
// Type-safe POST request
interface CreateUserRequest {
name: string;
email: string;
age?: number;
}
interface CreateUserResponse {
id: number;
success: boolean;
message: string;
}
const request: CreateUserRequest = {
name: 'Jane Smith',
email: 'jane@example.com',
age: 30
};
$.post('/api/users', request).done((response: CreateUserResponse) => {
if (response.success) {
console.log(`User created with ID: ${response.id}`);
} else {
console.error('Error:', response.message);
}
});// GET JSON data
$.getJSON('/api/config')
.done(config => {
console.log('Configuration:', config);
})
.fail(() => {
console.log('Failed to load configuration');
});
// GET JSON with parameters
$.getJSON('/api/search', { q: 'javascript', limit: 5 })
.done(results => {
console.log('Search results:', results);
});
// Type-safe JSON request
interface SearchResult {
title: string;
url: string;
snippet: string;
}
interface SearchResponse {
results: SearchResult[];
total: number;
page: number;
}
$.getJSON('/api/search', { q: 'typescript' })
.done((response: SearchResponse) => {
console.log(`Found ${response.total} results:`);
response.results.forEach(result => {
console.log(`- ${result.title}: ${result.url}`);
});
});// Complete AJAX request configuration
$.ajax({
url: '/api/users',
method: 'POST',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify({
name: 'Alice Johnson',
email: 'alice@example.com'
}),
headers: {
'X-API-Key': 'your-api-key',
'X-Request-ID': generateRequestId()
},
timeout: 5000,
beforeSend: function(xhr, settings) {
console.log('Sending request to:', settings.url);
xhr.setRequestHeader('Authorization', 'Bearer ' + getAuthToken());
},
success: function(data, textStatus, xhr) {
console.log('Success:', data);
console.log('Status:', textStatus);
console.log('Response headers:', xhr.getAllResponseHeaders());
},
error: function(xhr, textStatus, errorThrown) {
console.error('Error:', textStatus, errorThrown);
console.error('Response:', xhr.responseText);
},
complete: function(xhr, textStatus) {
console.log('Request completed with status:', textStatus);
}
});
// AJAX with custom context
const apiClient = {
baseUrl: '/api/v1',
token: 'auth-token',
request: function(endpoint: string, data: any) {
return $.ajax({
url: this.baseUrl + endpoint,
method: 'POST',
data: JSON.stringify(data),
contentType: 'application/json',
headers: {
'Authorization': `Bearer ${this.token}`
},
context: this,
success: this.handleSuccess,
error: this.handleError
});
},
handleSuccess: function(data: any) {
console.log('API success:', data);
},
handleError: function(xhr: JQuery.jqXHR) {
console.error('API error:', xhr.status, xhr.responseText);
}
};// File upload with FormData
function uploadFile(file: File) {
const formData = new FormData();
formData.append('file', file);
formData.append('category', 'documents');
return $.ajax({
url: '/api/upload',
type: 'POST',
data: formData,
processData: false,
contentType: false,
xhr: function() {
const xhr = new XMLHttpRequest();
// Upload progress
xhr.upload.addEventListener('progress', (event) => {
if (event.lengthComputable) {
const percentComplete = (event.loaded / event.total) * 100;
console.log(`Upload progress: ${percentComplete}%`);
}
});
return xhr;
},
success: function(response) {
console.log('Upload successful:', response);
},
error: function(xhr) {
console.error('Upload failed:', xhr.responseText);
}
});
}
// Multiple file upload
function uploadMultipleFiles(files: FileList) {
const formData = new FormData();
Array.from(files).forEach((file, index) => {
formData.append(`files[${index}]`, file);
});
return $.ajax({
url: '/api/upload-multiple',
type: 'POST',
data: formData,
processData: false,
contentType: false
});
}// Detailed error handling
$.ajax({
url: '/api/data',
method: 'GET',
timeout: 10000,
statusCode: {
200: function() {
console.log('Success!');
},
404: function() {
console.log('Resource not found');
},
500: function() {
console.log('Server error');
}
}
}).done(function(data) {
// Success handler
console.log('Data received:', data);
}).fail(function(xhr, textStatus, errorThrown) {
// Error handler
switch (textStatus) {
case 'timeout':
console.error('Request timed out');
break;
case 'abort':
console.error('Request was aborted');
break;
case 'error':
console.error('HTTP error:', xhr.status, errorThrown);
break;
case 'parsererror':
console.error('Failed to parse response');
break;
default:
console.error('Unknown error:', textStatus);
}
}).always(function() {
console.log('Request completed');
});
// Global error handler
$(document).ajaxError(function(event, xhr, settings, thrownError) {
console.error('Global AJAX error:', {
url: settings.url,
status: xhr.status,
error: thrownError
});
});// Retry failed requests
function makeRequest(url: string, data: any, maxRetries = 3): Promise<any> {
let attempts = 0;
function attempt(): Promise<any> {
return $.ajax({
url: url,
method: 'POST',
data: JSON.stringify(data),
contentType: 'application/json'
}).then(
response => response,
error => {
attempts++;
if (attempts < maxRetries && error.status >= 500) {
console.log(`Attempt ${attempts} failed, retrying...`);
return new Promise(resolve => {
setTimeout(() => resolve(attempt()), 1000 * attempts);
});
}
throw error;
}
);
}
return attempt();
}
// Usage
makeRequest('/api/save', userData)
.then(response => console.log('Saved:', response))
.catch(error => console.error('Failed after retries:', error));// Request data transformation
$.ajaxSetup({
beforeSend: function(xhr, settings) {
// Add timestamp to all requests
if (settings.data) {
const separator = settings.data.includes('?') ? '&' : '?';
settings.data += separator + 'timestamp=' + Date.now();
}
},
dataFilter: function(data, type) {
// Transform response data
if (type === 'json') {
const parsed = JSON.parse(data);
// Add metadata to all responses
parsed._meta = {
receivedAt: new Date().toISOString(),
processed: true
};
return JSON.stringify(parsed);
}
return data;
}
});
// Custom data converter
$.ajaxSetup({
converters: {
"text json": function(data) {
// Custom JSON parser with error handling
try {
return JSON.parse(data);
} catch (e) {
console.error('JSON parse error:', e);
return { error: 'Invalid JSON response' };
}
}
}
});// Request validation wrapper
function validateAndSend<T>(options: JQuery.AjaxSettings, validator?: (data: any) => boolean): JQuery.jqXHR {
if (validator && options.data && !validator(options.data)) {
const deferred = $.Deferred();
deferred.reject('Validation failed');
return deferred.promise() as JQuery.jqXHR;
}
return $.ajax(options);
}
// Email validation example
function isValidEmail(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
const userData = { name: 'John', email: 'john@example.com' };
validateAndSend({
url: '/api/users',
method: 'POST',
data: userData
}, (data) => {
return data.name && data.email && isValidEmail(data.email);
}).done(response => {
console.log('User created:', response);
}).fail(error => {
console.error('Validation or request failed:', error);
});// Cross-origin request with credentials
$.ajax({
url: 'https://api.external.com/data',
method: 'GET',
crossDomain: true,
xhrFields: {
withCredentials: true
},
headers: {
'Authorization': 'Bearer ' + token
}
}).done(data => {
console.log('External data:', data);
});
// Preflight request handling
$.ajax({
url: 'https://api.external.com/submit',
method: 'PUT',
contentType: 'application/json',
data: JSON.stringify(payload),
beforeSend: function(xhr) {
// Custom headers for CORS preflight
xhr.setRequestHeader('X-Custom-Header', 'value');
}
});// JSONP for cross-domain requests
$.ajax({
url: 'https://api.external.com/data',
dataType: 'jsonp',
jsonp: 'callback',
success: function(data) {
console.log('JSONP data:', data);
},
error: function() {
console.log('JSONP request failed');
}
});
// JSONP with custom callback name
$.ajax({
url: 'https://api.external.com/data',
dataType: 'jsonp',
jsonpCallback: 'myCustomCallback',
success: function(data) {
console.log('Data via custom callback:', data);
}
});
// $.getJSON with JSONP (automatic detection)
$.getJSON('https://api.external.com/data?callback=?')
.done(data => console.log('JSONP data:', data))
.fail(() => console.log('JSONP failed'));// Global AJAX configuration
$.ajaxSetup({
timeout: 30000,
cache: false,
contentType: 'application/json',
beforeSend: function(xhr, settings) {
// Add auth token to all requests
const token = localStorage.getItem('authToken');
if (token) {
xhr.setRequestHeader('Authorization', `Bearer ${token}`);
}
// Add CSRF token
const csrfToken = $('meta[name="csrf-token"]').attr('content');
if (csrfToken) {
xhr.setRequestHeader('X-CSRF-Token', csrfToken);
}
}
});
// Global event handlers
$(document).ajaxStart(function() {
$('#loading-indicator').show();
});
$(document).ajaxStop(function() {
$('#loading-indicator').hide();
});
$(document).ajaxSuccess(function(event, xhr, settings) {
console.log('AJAX success:', settings.url);
});
$(document).ajaxError(function(event, xhr, settings, thrownError) {
console.error('AJAX error:', settings.url, xhr.status, thrownError);
// Handle common errors globally
if (xhr.status === 401) {
// Redirect to login
window.location.href = '/login';
} else if (xhr.status === 403) {
alert('Access denied');
}
});// Request deduplication
const requestCache = new Map<string, Promise<any>>();
function cachedAjax(url: string, options: JQuery.AjaxSettings = {}): Promise<any> {
const cacheKey = url + JSON.stringify(options);
if (requestCache.has(cacheKey)) {
return requestCache.get(cacheKey)!;
}
const promise = $.ajax({ url, ...options }).promise();
requestCache.set(cacheKey, promise);
// Clear cache after 5 minutes
setTimeout(() => requestCache.delete(cacheKey), 5 * 60 * 1000);
return promise;
}
// Batch requests
function batchRequests<T>(requests: Array<() => JQuery.jqXHR>): Promise<T[]> {
return Promise.all(requests.map(req => req().promise()));
}
// Usage
const userRequests = [
() => $.get('/api/users/1'),
() => $.get('/api/users/2'),
() => $.get('/api/users/3')
];
batchRequests(userRequests).then(users => {
console.log('All users loaded:', users);
});
// Request queuing for rate limiting
class RequestQueue {
private queue: Array<() => JQuery.jqXHR> = [];
private processing = false;
private readonly delay = 100; // ms between requests
add(requestFn: () => JQuery.jqXHR): Promise<any> {
return new Promise((resolve, reject) => {
this.queue.push(() => {
return requestFn().done(resolve).fail(reject);
});
this.process();
});
}
private async process() {
if (this.processing || this.queue.length === 0) return;
this.processing = true;
while (this.queue.length > 0) {
const request = this.queue.shift()!;
request();
await new Promise(resolve => setTimeout(resolve, this.delay));
}
this.processing = false;
}
}The AJAX system provides comprehensive HTTP communication capabilities with full TypeScript support, enabling robust client-server interactions with proper error handling, type safety, and performance optimization.