or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ajax-operations.mdcombination-operators.mdcore-types.mderror-handling.mdfetch-operations.mdfiltering-operators.mdindex.mdobservable-creation.mdschedulers.mdsubjects.mdtesting-utilities.mdtransformation-operators.mdwebsocket-operations.md

ajax-operations.mddocs/

0

# AJAX Operations

1

2

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

3

4

## Capabilities

5

6

### ajax Function

7

8

Core function for creating HTTP request observables.

9

10

```typescript { .api }

11

/**

12

* Create observable HTTP requests with comprehensive configuration

13

* @param request - URL string or detailed configuration object

14

* @returns Observable emitting AjaxResponse

15

*/

16

function ajax<T>(request: string | AjaxConfig): Observable<AjaxResponse<T>>;

17

18

/**

19

* Create GET request observable returning JSON response

20

* @param url - URL to request

21

* @param headers - Optional request headers

22

* @returns Observable emitting parsed JSON response

23

*/

24

function ajax.getJSON<T>(url: string, headers?: Record<string, any>): Observable<T>;

25

26

/**

27

* Create GET request observable

28

* @param url - URL to request

29

* @param headers - Optional request headers

30

* @returns Observable emitting AjaxResponse

31

*/

32

function ajax.get(url: string, headers?: Record<string, any>): Observable<AjaxResponse<any>>;

33

34

/**

35

* Create POST request observable

36

* @param url - URL to request

37

* @param body - Request body

38

* @param headers - Optional request headers

39

* @returns Observable emitting AjaxResponse

40

*/

41

function ajax.post(url: string, body?: any, headers?: Record<string, any>): Observable<AjaxResponse<any>>;

42

43

/**

44

* Create PUT request observable

45

* @param url - URL to request

46

* @param body - Request body

47

* @param headers - Optional request headers

48

* @returns Observable emitting AjaxResponse

49

*/

50

function ajax.put(url: string, body?: any, headers?: Record<string, any>): Observable<AjaxResponse<any>>;

51

52

/**

53

* Create PATCH request observable

54

* @param url - URL to request

55

* @param body - Request body

56

* @param headers - Optional request headers

57

* @returns Observable emitting AjaxResponse

58

*/

59

function ajax.patch(url: string, body?: any, headers?: Record<string, any>): Observable<AjaxResponse<any>>;

60

61

/**

62

* Create DELETE request observable

63

* @param url - URL to request

64

* @param headers - Optional request headers

65

* @returns Observable emitting AjaxResponse

66

*/

67

function ajax.delete(url: string, headers?: Record<string, any>): Observable<AjaxResponse<any>>;

68

```

69

70

**Usage Examples:**

71

72

```typescript

73

import { ajax } from "rxjs/ajax";

74

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

75

import { of } from "rxjs";

76

77

// Simple GET request

78

ajax.getJSON<User>('/api/users/123').subscribe(

79

user => console.log('User:', user),

80

err => console.error('Error:', err)

81

);

82

83

// GET with headers

84

ajax.get('/api/data', {

85

'Authorization': 'Bearer token123',

86

'Content-Type': 'application/json'

87

}).subscribe(response => {

88

console.log('Status:', response.status);

89

console.log('Data:', response.response);

90

});

91

92

// POST request

93

ajax.post('/api/users', {

94

name: 'John Doe',

95

email: 'john@example.com'

96

}, {

97

'Content-Type': 'application/json'

98

}).subscribe(

99

response => console.log('Created user:', response.response),

100

err => console.error('Creation failed:', err)

101

);

102

103

// Advanced configuration

104

ajax({

105

url: '/api/upload',

106

method: 'POST',

107

body: formData,

108

timeout: 30000,

109

responseType: 'json',

110

withCredentials: true

111

}).subscribe(

112

response => console.log('Upload successful:', response),

113

err => console.error('Upload failed:', err)

114

);

115

```

116

117

### AjaxConfig Interface

118

119

Comprehensive configuration for HTTP requests.

120

121

```typescript { .api }

122

/**

123

* Configuration object for AJAX requests

124

*/

125

interface AjaxConfig {

126

/** Request URL */

127

url?: string;

128

129

/** HTTP method (GET, POST, PUT, DELETE, etc.) */

130

method?: string;

131

132

/** Request headers object */

133

headers?: Record<string, any>;

134

135

/** Request body (any serializable data) */

136

body?: any;

137

138

/** Include credentials in cross-origin requests */

139

withCredentials?: boolean;

140

141

/** Username for HTTP authentication */

142

user?: string;

143

144

/** Password for HTTP authentication */

145

password?: string;

146

147

/** Request timeout in milliseconds */

148

timeout?: number;

149

150

/** Response type expected */

151

responseType?: XMLHttpRequestResponseType;

152

153

/** Custom XMLHttpRequest creation function */

154

createXHR?: () => XMLHttpRequest;

155

156

/** Progress event handler */

157

progressSubscriber?: Subscriber<any>;

158

159

/** Include response headers in result */

160

includeDownloadProgress?: boolean;

161

162

/** Include upload progress events */

163

includeUploadProgress?: boolean;

164

165

/** Custom result selector function */

166

resultSelector?: (response: AjaxResponse<any>) => any;

167

168

/** Cross-domain request handling */

169

crossDomain?: boolean;

170

}

171

172

/**

173

* Response type values for XMLHttpRequest

174

*/

175

type XMLHttpRequestResponseType = "" | "arraybuffer" | "blob" | "document" | "json" | "text";

176

```

177

178

### AjaxResponse Class

179

180

Wrapper for HTTP responses with metadata.

181

182

```typescript { .api }

183

/**

184

* Wrapper for HTTP response data and metadata

185

*/

186

class AjaxResponse<T> {

187

/** Parsed response data */

188

readonly response: T;

189

190

/** HTTP status code */

191

readonly status: number;

192

193

/** HTTP status text */

194

readonly responseText: string;

195

196

/** Response headers */

197

readonly responseHeaders: Record<string, string>;

198

199

/** Original request configuration */

200

readonly request: AjaxConfig;

201

202

/** Response type */

203

readonly responseType: XMLHttpRequestResponseType;

204

205

/** Total bytes loaded */

206

readonly loaded: number;

207

208

/** Total bytes to load */

209

readonly total: number;

210

211

/** Original XMLHttpRequest object */

212

readonly originalEvent: ProgressEvent;

213

214

/** Original XMLHttpRequest instance */

215

readonly xhr: XMLHttpRequest;

216

217

constructor(

218

originalEvent: Event,

219

xhr: XMLHttpRequest,

220

request: AjaxConfig

221

);

222

}

223

```

224

225

### Error Classes

226

227

Specialized error types for HTTP request failures.

228

229

```typescript { .api }

230

/**

231

* Error for general AJAX request failures

232

*/

233

class AjaxError extends Error {

234

/** Error name */

235

readonly name: "AjaxError";

236

237

/** HTTP status code */

238

readonly status: number;

239

240

/** Response text */

241

readonly responseText: string;

242

243

/** Original XMLHttpRequest */

244

readonly xhr: XMLHttpRequest;

245

246

/** Original request configuration */

247

readonly request: AjaxConfig;

248

249

constructor(message: string, xhr: XMLHttpRequest, request: AjaxConfig);

250

}

251

252

/**

253

* Error for AJAX request timeouts

254

*/

255

class AjaxTimeoutError extends AjaxError {

256

/** Error name */

257

readonly name: "AjaxTimeoutError";

258

259

constructor(xhr: XMLHttpRequest, request: AjaxConfig);

260

}

261

```

262

263

## Advanced AJAX Patterns

264

265

### Request Interceptors

266

267

```typescript

268

import { ajax } from "rxjs/ajax";

269

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

270

271

// Create HTTP client with interceptors

272

class HttpClient {

273

private baseURL = 'https://api.example.com';

274

private authToken = '';

275

276

setAuthToken(token: string) {

277

this.authToken = token;

278

}

279

280

private createRequest(config: AjaxConfig): Observable<AjaxResponse<any>> {

281

const fullConfig: AjaxConfig = {

282

...config,

283

url: `${this.baseURL}${config.url}`,

284

headers: {

285

'Content-Type': 'application/json',

286

...(this.authToken && { 'Authorization': `Bearer ${this.authToken}` }),

287

...config.headers

288

},

289

timeout: 10000

290

};

291

292

return ajax(fullConfig).pipe(

293

tap(response => {

294

console.log(`${config.method} ${config.url}:`, response.status);

295

}),

296

retryWhen(errors =>

297

errors.pipe(

298

delay(1000),

299

take(3) // Retry up to 3 times

300

)

301

),

302

catchError(err => {

303

if (err instanceof AjaxTimeoutError) {

304

console.error('Request timeout:', config.url);

305

} else if (err instanceof AjaxError) {

306

console.error(`HTTP Error ${err.status}:`, err.responseText);

307

}

308

throw err;

309

})

310

);

311

}

312

313

get<T>(url: string, headers?: Record<string, any>): Observable<T> {

314

return this.createRequest({ url, method: 'GET', headers }).pipe(

315

map(response => response.response)

316

);

317

}

318

319

post<T>(url: string, body: any, headers?: Record<string, any>): Observable<T> {

320

return this.createRequest({

321

url,

322

method: 'POST',

323

body: JSON.stringify(body),

324

headers

325

}).pipe(

326

map(response => response.response)

327

);

328

}

329

}

330

331

const httpClient = new HttpClient();

332

httpClient.setAuthToken('your-token-here');

333

334

// Usage

335

httpClient.get<User>('/users/123').subscribe(user => {

336

console.log('User loaded:', user);

337

});

338

```

339

340

### File Upload with Progress

341

342

```typescript

343

import { ajax } from "rxjs/ajax";

344

import { Subject } from "rxjs";

345

346

function uploadFile(file: File, url: string): Observable<AjaxResponse<any>> {

347

const formData = new FormData();

348

formData.append('file', file);

349

350

const progressSubject = new Subject<number>();

351

352

const upload$ = ajax({

353

url,

354

method: 'POST',

355

body: formData,

356

progressSubscriber: progressSubject,

357

includeUploadProgress: true

358

});

359

360

// Monitor progress

361

progressSubject.subscribe(progress => {

362

const percentage = (progress.loaded / progress.total) * 100;

363

console.log(`Upload progress: ${percentage.toFixed(1)}%`);

364

updateProgressBar(percentage);

365

});

366

367

return upload$;

368

}

369

370

// Usage

371

const fileInput = document.getElementById('file') as HTMLInputElement;

372

fileInput.addEventListener('change', (event) => {

373

const file = event.target.files[0];

374

if (file) {

375

uploadFile(file, '/api/upload').subscribe(

376

response => console.log('Upload complete:', response.response),

377

err => console.error('Upload failed:', err)

378

);

379

}

380

});

381

```

382

383

### Response Caching

384

385

```typescript

386

import { ajax } from "rxjs/ajax";

387

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

388

389

class CachedHttpClient {

390

private cache = new Map<string, Observable<any>>();

391

392

get<T>(url: string, cacheKey?: string): Observable<T> {

393

const key = cacheKey || url;

394

395

if (!this.cache.has(key)) {

396

const request$ = ajax.getJSON<T>(url).pipe(

397

tap(data => console.log(`Cached: ${key}`)),

398

shareReplay(1) // Share and replay last emission

399

);

400

401

this.cache.set(key, request$);

402

403

// Auto-expire cache after 5 minutes

404

setTimeout(() => {

405

this.cache.delete(key);

406

console.log(`Cache expired: ${key}`);

407

}, 5 * 60 * 1000);

408

}

409

410

return this.cache.get(key)!;

411

}

412

413

clearCache(key?: string) {

414

if (key) {

415

this.cache.delete(key);

416

} else {

417

this.cache.clear();

418

}

419

}

420

}

421

422

const cachedClient = new CachedHttpClient();

423

424

// First call - makes HTTP request

425

cachedClient.get<User[]>('/api/users').subscribe(users => {

426

console.log('Users (from server):', users);

427

});

428

429

// Second call - returns cached data

430

cachedClient.get<User[]>('/api/users').subscribe(users => {

431

console.log('Users (from cache):', users);

432

});

433

```

434

435

### Parallel Requests

436

437

```typescript

438

import { ajax } from "rxjs/ajax";

439

import { forkJoin, combineLatest } from "rxjs";

440

import { map } from "rxjs/operators";

441

442

// Load multiple resources in parallel

443

const userRequest$ = ajax.getJSON<User>('/api/user/123');

444

const postsRequest$ = ajax.getJSON<Post[]>('/api/user/123/posts');

445

const commentsRequest$ = ajax.getJSON<Comment[]>('/api/user/123/comments');

446

447

// Wait for all to complete

448

forkJoin({

449

user: userRequest$,

450

posts: postsRequest$,

451

comments: commentsRequest$

452

}).subscribe(({ user, posts, comments }) => {

453

console.log('All data loaded:', { user, posts, comments });

454

});

455

456

// Combine latest values as they arrive

457

combineLatest([

458

userRequest$,

459

postsRequest$,

460

commentsRequest$

461

]).pipe(

462

map(([user, posts, comments]) => ({ user, posts, comments }))

463

).subscribe(data => {

464

console.log('Combined data:', data);

465

});

466

```

467

468

## Types

469

470

```typescript { .api }

471

interface AjaxRequest extends AjaxConfig {

472

url: string;

473

method: string;

474

}

475

476

type AjaxDirection = "upload" | "download";

477

478

interface User {

479

id: number;

480

name: string;

481

email: string;

482

}

483

484

interface Post {

485

id: number;

486

title: string;

487

content: string;

488

userId: number;

489

}

490

491

interface Comment {

492

id: number;

493

text: string;

494

postId: number;

495

userId: number;

496

}

497

```