0
# Network APIs
1
2
Comprehensive networking capabilities including HTTP requests with interceptor support, designed for web environments using modern fetch API with Mini Program compatibility.
3
4
## Capabilities
5
6
### HTTP Request API
7
8
Full-featured HTTP client supporting all standard methods, headers, data formats, and advanced options.
9
10
```typescript { .api }
11
/**
12
* Make HTTP request with full configuration support
13
* @param options - Request configuration options
14
* @returns Promise resolving to response with data, status, and headers
15
*/
16
function request(options: RequestOption): Promise<RequestResult>;
17
18
interface RequestOption {
19
/** Target URL for the request (required) */
20
url: string;
21
/** Request body data (JSON serialized for non-GET requests) */
22
data?: any;
23
/** HTTP headers object */
24
header?: Record<string, string>;
25
/** HTTP method (default: 'GET') */
26
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
27
/** Expected response data type (default: 'json') */
28
dataType?: 'json' | 'text' | 'base64';
29
/** Response type for binary data (default: 'text') */
30
responseType?: 'text' | 'json' | 'arraybuffer';
31
/** Request timeout in milliseconds (default: 60000) */
32
timeout?: number;
33
/** Enable HTTP/2 support (browser dependent) */
34
enableHttp2?: boolean;
35
/** Enable QUIC support (browser dependent) */
36
enableQuic?: boolean;
37
/** Enable response caching (browser dependent) */
38
enableCache?: boolean;
39
/** Enable credentials for cross-origin requests */
40
credentials?: boolean;
41
/** Success callback function */
42
success?: (result: RequestResult) => void;
43
/** Failure callback function */
44
fail?: (error: any) => void;
45
/** Completion callback function */
46
complete?: (result: RequestResult | any) => void;
47
}
48
49
interface RequestResult {
50
/** Response data (parsed based on dataType) */
51
data: any;
52
/** HTTP status code */
53
statusCode: number;
54
/** Response headers object */
55
header: Record<string, string>;
56
/** Response cookies (if any) */
57
cookies?: string[];
58
/** Error message (if request failed) */
59
errMsg?: string;
60
}
61
```
62
63
**Usage Examples:**
64
65
```typescript
66
import { request } from "@tarojs/taro-h5";
67
68
// Basic GET request
69
const getUserData = async (userId: string) => {
70
try {
71
const response = await request({
72
url: `https://api.example.com/users/${userId}`,
73
method: 'GET',
74
header: {
75
'Authorization': 'Bearer token123',
76
'Content-Type': 'application/json'
77
}
78
});
79
80
console.log('User data:', response.data);
81
console.log('Status:', response.statusCode);
82
return response.data;
83
} catch (error) {
84
console.error('Failed to fetch user:', error);
85
throw error;
86
}
87
};
88
89
// POST request with data
90
const createUser = async (userData: any) => {
91
const response = await request({
92
url: 'https://api.example.com/users',
93
method: 'POST',
94
data: userData,
95
header: {
96
'Content-Type': 'application/json',
97
'Authorization': 'Bearer token123'
98
},
99
timeout: 10000
100
});
101
102
return response.data;
103
};
104
105
// PUT request for updates
106
const updateUserProfile = async (userId: string, profileData: any) => {
107
const response = await request({
108
url: `https://api.example.com/users/${userId}`,
109
method: 'PUT',
110
data: profileData,
111
header: {
112
'Content-Type': 'application/json',
113
'X-Request-ID': Date.now().toString()
114
}
115
});
116
117
return response.statusCode === 200;
118
};
119
120
// DELETE request
121
const deleteUser = async (userId: string) => {
122
await request({
123
url: `https://api.example.com/users/${userId}`,
124
method: 'DELETE',
125
header: {
126
'Authorization': 'Bearer token123'
127
}
128
});
129
};
130
```
131
132
### Request Interceptors
133
134
Powerful interceptor system for modifying requests and responses globally across the application.
135
136
```typescript { .api }
137
/**
138
* Add request interceptor to modify requests before they are sent
139
* @param interceptor - Interceptor function or object
140
*/
141
function addInterceptor(interceptor: Interceptor): void;
142
143
/**
144
* Remove all registered interceptors
145
*/
146
function cleanInterceptors(): void;
147
148
interface Interceptor {
149
/** Request interceptor function */
150
request?: (config: RequestOption) => RequestOption | Promise<RequestOption>;
151
/** Response interceptor function */
152
response?: (response: RequestResult) => RequestResult | Promise<RequestResult>;
153
/** Error interceptor function */
154
responseError?: (error: any) => any | Promise<any>;
155
}
156
157
// Alternative function-based interceptor
158
type InterceptorFunction = (config: RequestOption) => RequestOption | Promise<RequestOption>;
159
```
160
161
### File Download API
162
163
Full-featured file download functionality with progress tracking and binary data support.
164
165
```typescript { .api }
166
/**
167
* Download file from remote server to temporary local path
168
* @param options - Download configuration options
169
* @returns Promise resolving to download task with progress tracking
170
*/
171
function downloadFile(options: DownloadFileOption): Promise<DownloadFileResult> & DownloadTask;
172
173
interface DownloadFileOption {
174
/** Target URL for file download (required) */
175
url: string;
176
/** HTTP headers object */
177
header?: Record<string, string>;
178
/** Include credentials for cross-origin requests */
179
withCredentials?: boolean;
180
/** Request timeout in milliseconds (default: 60000) */
181
timeout?: number;
182
/** Success callback function */
183
success?: (result: DownloadFileResult) => void;
184
/** Failure callback function */
185
fail?: (error: any) => void;
186
/** Completion callback function */
187
complete?: (result: DownloadFileResult | any) => void;
188
}
189
190
interface DownloadFileResult {
191
/** Temporary file path (blob URL) */
192
tempFilePath: string;
193
/** HTTP status code */
194
statusCode: number;
195
/** Error message (if download failed) */
196
errMsg?: string;
197
}
198
199
interface DownloadTask {
200
/** Abort the download operation */
201
abort(): void;
202
/** Monitor HTTP Response Header events */
203
onHeadersReceived(callback: (res: { header: string }) => void): void;
204
/** Remove HTTP Response Header event listener */
205
offHeadersReceived(callback: (res: { header: string }) => void): void;
206
/** Monitor download progress events */
207
onProgressUpdate(callback: (res: DownloadProgressResult) => void): void;
208
/** Remove download progress event listener */
209
offProgressUpdate(callback: (res: DownloadProgressResult) => void): void;
210
}
211
212
interface DownloadProgressResult {
213
/** Download progress percentage (0-100) */
214
progress: number;
215
/** Total bytes written so far */
216
totalBytesWritten: number;
217
/** Expected total bytes to write */
218
totalBytesExpectedToWrite: number;
219
}
220
```
221
222
**Usage Examples:**
223
224
```typescript
225
import { downloadFile } from "@tarojs/taro-h5";
226
227
// Basic file download
228
const downloadImage = async () => {
229
try {
230
const result = await downloadFile({
231
url: 'https://example.com/image.jpg',
232
header: {
233
'Authorization': 'Bearer token123'
234
}
235
});
236
237
console.log('Downloaded to:', result.tempFilePath);
238
console.log('Status:', result.statusCode);
239
240
// Use the temporary file path (blob URL)
241
const img = document.createElement('img');
242
img.src = result.tempFilePath;
243
document.body.appendChild(img);
244
245
} catch (error) {
246
console.error('Download failed:', error);
247
}
248
};
249
250
// Download with progress tracking
251
const downloadWithProgress = () => {
252
const task = downloadFile({
253
url: 'https://example.com/large-file.zip',
254
success: (res) => {
255
console.log('Download completed:', res.tempFilePath);
256
},
257
fail: (error) => {
258
console.error('Download failed:', error);
259
}
260
});
261
262
// Track download progress
263
task.onProgressUpdate((res) => {
264
console.log(`Progress: ${res.progress}%`);
265
console.log(`Downloaded: ${res.totalBytesWritten} / ${res.totalBytesExpectedToWrite} bytes`);
266
267
// Update UI progress bar
268
updateProgressBar(res.progress);
269
});
270
271
// Handle headers received
272
task.onHeadersReceived((res) => {
273
console.log('Headers received:', res.header);
274
});
275
276
// Cancel download if needed
277
setTimeout(() => {
278
task.abort();
279
console.log('Download cancelled');
280
}, 10000); // Cancel after 10 seconds
281
};
282
```
283
284
### File Upload API
285
286
Multipart form data upload functionality with progress tracking and metadata support.
287
288
```typescript { .api }
289
/**
290
* Upload local file to remote server using multipart/form-data
291
* @param options - Upload configuration options
292
* @returns Promise resolving to upload task with progress tracking
293
*/
294
function uploadFile(options: UploadFileOption): Promise<UploadFileResult> & UploadTask;
295
296
interface UploadFileOption {
297
/** Target URL for file upload (required) */
298
url: string;
299
/** File path to upload (blob URL or File object) */
300
filePath: string;
301
/** Form field name for the file (required) */
302
name: string;
303
/** HTTP headers object */
304
header?: Record<string, string>;
305
/** Additional form data fields */
306
formData?: Record<string, string>;
307
/** Request timeout in milliseconds (default: 60000) */
308
timeout?: number;
309
/** Custom filename for the uploaded file */
310
fileName?: string;
311
/** Include credentials for cross-origin requests */
312
withCredentials?: boolean;
313
/** Success callback function */
314
success?: (result: UploadFileResult) => void;
315
/** Failure callback function */
316
fail?: (error: any) => void;
317
/** Completion callback function */
318
complete?: (result: UploadFileResult | any) => void;
319
}
320
321
interface UploadFileResult {
322
/** Server response data */
323
data: string;
324
/** HTTP status code */
325
statusCode: number;
326
/** Error message (if upload failed) */
327
errMsg?: string;
328
}
329
330
interface UploadTask {
331
/** Abort the upload operation */
332
abort(): void;
333
/** Monitor HTTP Response Header events */
334
onHeadersReceived(callback: (res: { header: string }) => void): void;
335
/** Remove HTTP Response Header event listener */
336
offHeadersReceived(callback: (res: { header: string }) => void): void;
337
/** Monitor upload progress events */
338
onProgressUpdate(callback: (res: UploadProgressResult) => void): void;
339
/** Remove upload progress event listener */
340
offProgressUpdate(callback: (res: UploadProgressResult) => void): void;
341
}
342
343
interface UploadProgressResult {
344
/** Upload progress percentage (0-100) */
345
progress: number;
346
/** Total bytes sent so far */
347
totalBytesSent: number;
348
/** Expected total bytes to send */
349
totalBytesExpectedToSend: number;
350
}
351
```
352
353
**Usage Examples:**
354
355
```typescript
356
import { uploadFile } from "@tarojs/taro-h5";
357
358
// Basic file upload
359
const uploadImage = async (fileBlob: Blob) => {
360
try {
361
// Create blob URL from file
362
const filePath = URL.createObjectURL(fileBlob);
363
364
const result = await uploadFile({
365
url: 'https://api.example.com/upload',
366
filePath: filePath,
367
name: 'image',
368
fileName: 'photo.jpg',
369
header: {
370
'Authorization': 'Bearer token123'
371
},
372
formData: {
373
'userId': '12345',
374
'category': 'profile'
375
}
376
});
377
378
console.log('Upload completed');
379
console.log('Server response:', result.data);
380
console.log('Status:', result.statusCode);
381
382
// Clean up blob URL
383
URL.revokeObjectURL(filePath);
384
385
} catch (error) {
386
console.error('Upload failed:', error);
387
}
388
};
389
390
// Upload with progress tracking
391
const uploadWithProgress = (fileInput: HTMLInputElement) => {
392
const file = fileInput.files?.[0];
393
if (!file) return;
394
395
const filePath = URL.createObjectURL(file);
396
397
const task = uploadFile({
398
url: 'https://api.example.com/upload',
399
filePath: filePath,
400
name: 'file',
401
fileName: file.name,
402
formData: {
403
'timestamp': Date.now().toString(),
404
'fileSize': file.size.toString()
405
},
406
success: (res) => {
407
console.log('Upload successful:', JSON.parse(res.data));
408
URL.revokeObjectURL(filePath);
409
},
410
fail: (error) => {
411
console.error('Upload failed:', error);
412
URL.revokeObjectURL(filePath);
413
}
414
});
415
416
// Track upload progress
417
task.onProgressUpdate((res) => {
418
console.log(`Upload progress: ${res.progress}%`);
419
console.log(`Uploaded: ${res.totalBytesSent} / ${res.totalBytesExpectedToSend} bytes`);
420
421
// Update UI progress
422
const progressPercent = res.progress;
423
updateUploadProgress(progressPercent);
424
});
425
426
// Handle response headers
427
task.onHeadersReceived((res) => {
428
console.log('Response headers received:', res.header);
429
});
430
431
// Cancel upload if needed
432
const cancelButton = document.getElementById('cancel-upload');
433
cancelButton?.addEventListener('click', () => {
434
task.abort();
435
console.log('Upload cancelled');
436
URL.revokeObjectURL(filePath);
437
});
438
};
439
440
// Multiple file upload
441
const uploadMultipleFiles = async (files: FileList) => {
442
const uploadPromises = Array.from(files).map(async (file) => {
443
const filePath = URL.createObjectURL(file);
444
445
try {
446
const result = await uploadFile({
447
url: 'https://api.example.com/upload',
448
filePath: filePath,
449
name: 'files',
450
fileName: file.name
451
});
452
453
URL.revokeObjectURL(filePath);
454
return { success: true, fileName: file.name, result };
455
456
} catch (error) {
457
URL.revokeObjectURL(filePath);
458
return { success: false, fileName: file.name, error };
459
}
460
});
461
462
const results = await Promise.all(uploadPromises);
463
464
results.forEach(result => {
465
if (result.success) {
466
console.log(`✓ ${result.fileName} uploaded successfully`);
467
} else {
468
console.error(`✗ ${result.fileName} failed:`, result.error);
469
}
470
});
471
};
472
```
473
474
### WebSocket APIs
475
476
Real-time bidirectional communication support using WebSocket protocol with task-based management.
477
478
```typescript { .api }
479
/**
480
* Establish WebSocket connection to remote server
481
* @param options - WebSocket connection options
482
* @returns Promise resolving to SocketTask for connection management
483
*/
484
function connectSocket(options: ConnectSocketOption): Promise<SocketTask>;
485
486
interface ConnectSocketOption {
487
/** WebSocket server URL (must use ws:// or wss://) */
488
url: string;
489
/** WebSocket sub-protocols array */
490
protocols?: string[];
491
/** Success callback function */
492
success?: (res: { socketTaskId?: number }) => void;
493
/** Failure callback function */
494
fail?: (error: any) => void;
495
/** Completion callback function */
496
complete?: (res: any) => void;
497
}
498
499
interface SocketTask {
500
/** Send data through WebSocket connection */
501
send(options: SocketSendOption): Promise<void>;
502
/** Close WebSocket connection */
503
close(options?: SocketCloseOption): Promise<void>;
504
/** Listen for connection open event */
505
onOpen(callback: (res: any) => void): void;
506
/** Remove connection open event listener */
507
offOpen(callback: (res: any) => void): void;
508
/** Listen for message received event */
509
onMessage(callback: (res: SocketMessageResult) => void): void;
510
/** Remove message received event listener */
511
offMessage(callback: (res: SocketMessageResult) => void): void;
512
/** Listen for connection error event */
513
onError(callback: (res: any) => void): void;
514
/** Remove connection error event listener */
515
offError(callback: (res: any) => void): void;
516
/** Listen for connection close event */
517
onClose(callback: (res: SocketCloseResult) => void): void;
518
/** Remove connection close event listener */
519
offClose(callback: (res: SocketCloseResult) => void): void;
520
}
521
522
interface SocketSendOption {
523
/** Data to send (string or ArrayBuffer) */
524
data: string | ArrayBuffer;
525
/** Success callback function */
526
success?: () => void;
527
/** Failure callback function */
528
fail?: (error: any) => void;
529
/** Completion callback function */
530
complete?: () => void;
531
}
532
533
interface SocketCloseOption {
534
/** Close code (default: 1000) */
535
code?: number;
536
/** Close reason */
537
reason?: string;
538
/** Success callback function */
539
success?: () => void;
540
/** Failure callback function */
541
fail?: (error: any) => void;
542
/** Completion callback function */
543
complete?: () => void;
544
}
545
546
interface SocketMessageResult {
547
/** Received message data */
548
data: string | ArrayBuffer;
549
}
550
551
interface SocketCloseResult {
552
/** Close code */
553
code: number;
554
/** Close reason */
555
reason: string;
556
/** Whether close was initiated by client */
557
wasClean: boolean;
558
}
559
```
560
561
**Usage Examples:**
562
563
```typescript
564
import { connectSocket } from "@tarojs/taro-h5";
565
566
// Basic WebSocket connection
567
const connectToWebSocket = async () => {
568
try {
569
const socketTask = await connectSocket({
570
url: 'wss://api.example.com/websocket',
571
protocols: ['chat', 'notifications']
572
});
573
574
// Handle connection opened
575
socketTask.onOpen((res) => {
576
console.log('WebSocket connected');
577
578
// Send initial message
579
socketTask.send({
580
data: JSON.stringify({
581
type: 'join',
582
userId: '12345'
583
})
584
});
585
});
586
587
// Handle incoming messages
588
socketTask.onMessage((res) => {
589
const message = JSON.parse(res.data as string);
590
console.log('Received message:', message);
591
592
// Process different message types
593
switch (message.type) {
594
case 'chat':
595
displayChatMessage(message.content);
596
break;
597
case 'notification':
598
showNotification(message.title, message.body);
599
break;
600
default:
601
console.log('Unknown message type:', message.type);
602
}
603
});
604
605
// Handle connection errors
606
socketTask.onError((error) => {
607
console.error('WebSocket error:', error);
608
});
609
610
// Handle connection closed
611
socketTask.onClose((res) => {
612
console.log('WebSocket closed:', res.code, res.reason);
613
614
// Attempt reconnection if not intentionally closed
615
if (res.code !== 1000) {
616
console.log('Attempting to reconnect...');
617
setTimeout(connectToWebSocket, 3000);
618
}
619
});
620
621
return socketTask;
622
623
} catch (error) {
624
console.error('Failed to connect WebSocket:', error);
625
}
626
};
627
628
// Chat application example
629
class WebSocketChat {
630
private socketTask: SocketTask | null = null;
631
private reconnectAttempts = 0;
632
private maxReconnectAttempts = 5;
633
634
async connect(userId: string) {
635
try {
636
this.socketTask = await connectSocket({
637
url: `wss://chat.example.com/ws?userId=${userId}`,
638
success: () => {
639
console.log('Chat connection initiated');
640
this.reconnectAttempts = 0;
641
},
642
fail: (error) => {
643
console.error('Chat connection failed:', error);
644
this.handleReconnect();
645
}
646
});
647
648
this.setupEventHandlers();
649
650
} catch (error) {
651
console.error('Failed to establish chat connection:', error);
652
this.handleReconnect();
653
}
654
}
655
656
private setupEventHandlers() {
657
if (!this.socketTask) return;
658
659
this.socketTask.onOpen(() => {
660
console.log('Chat connection established');
661
this.sendMessage({
662
type: 'user_online',
663
timestamp: Date.now()
664
});
665
});
666
667
this.socketTask.onMessage((res) => {
668
const message = JSON.parse(res.data as string);
669
this.handleIncomingMessage(message);
670
});
671
672
this.socketTask.onError((error) => {
673
console.error('Chat connection error:', error);
674
});
675
676
this.socketTask.onClose((res) => {
677
console.log('Chat connection closed');
678
if (res.code !== 1000) {
679
this.handleReconnect();
680
}
681
});
682
}
683
684
sendChatMessage(text: string) {
685
this.sendMessage({
686
type: 'chat',
687
text: text,
688
timestamp: Date.now()
689
});
690
}
691
692
sendTypingIndicator(isTyping: boolean) {
693
this.sendMessage({
694
type: 'typing',
695
isTyping: isTyping
696
});
697
}
698
699
private sendMessage(message: any) {
700
if (!this.socketTask) {
701
console.error('No active WebSocket connection');
702
return;
703
}
704
705
this.socketTask.send({
706
data: JSON.stringify(message),
707
success: () => {
708
console.log('Message sent successfully');
709
},
710
fail: (error) => {
711
console.error('Failed to send message:', error);
712
}
713
});
714
}
715
716
private handleIncomingMessage(message: any) {
717
switch (message.type) {
718
case 'chat':
719
this.displayChatMessage(message);
720
break;
721
case 'user_joined':
722
this.showUserJoined(message.userId);
723
break;
724
case 'user_left':
725
this.showUserLeft(message.userId);
726
break;
727
case 'typing':
728
this.showTypingIndicator(message.userId, message.isTyping);
729
break;
730
default:
731
console.log('Unknown message type:', message.type);
732
}
733
}
734
735
private handleReconnect() {
736
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
737
console.error('Max reconnection attempts reached');
738
return;
739
}
740
741
this.reconnectAttempts++;
742
const delay = Math.pow(2, this.reconnectAttempts) * 1000; // Exponential backoff
743
744
console.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
745
746
setTimeout(() => {
747
this.connect(this.getCurrentUserId());
748
}, delay);
749
}
750
751
async disconnect() {
752
if (!this.socketTask) return;
753
754
try {
755
await this.socketTask.close({
756
code: 1000,
757
reason: 'User disconnected'
758
});
759
760
console.log('Chat disconnected successfully');
761
762
} catch (error) {
763
console.error('Error disconnecting chat:', error);
764
}
765
766
this.socketTask = null;
767
}
768
769
// Placeholder methods for UI integration
770
private displayChatMessage(message: any) {
771
console.log(`${message.userId}: ${message.text}`);
772
}
773
774
private showUserJoined(userId: string) {
775
console.log(`${userId} joined the chat`);
776
}
777
778
private showUserLeft(userId: string) {
779
console.log(`${userId} left the chat`);
780
}
781
782
private showTypingIndicator(userId: string, isTyping: boolean) {
783
console.log(`${userId} is ${isTyping ? 'typing' : 'not typing'}`);
784
}
785
786
private getCurrentUserId(): string {
787
return 'current-user-id'; // Get from app state
788
}
789
}
790
791
// Usage
792
const chat = new WebSocketChat();
793
await chat.connect('user123');
794
795
// Send messages
796
chat.sendChatMessage('Hello everyone!');
797
chat.sendTypingIndicator(true);
798
799
// Later disconnect
800
await chat.disconnect();
801
```
802
803
**Usage Examples:**
804
805
```typescript
806
import { addInterceptor, cleanInterceptors, request } from "@tarojs/taro-h5";
807
808
// Add authentication interceptor
809
addInterceptor({
810
request: (config) => {
811
// Add auth token to all requests
812
const token = getStorageSync('authToken');
813
if (token) {
814
config.header = {
815
...config.header,
816
'Authorization': `Bearer ${token}`
817
};
818
}
819
820
// Add request ID for tracking
821
config.header['X-Request-ID'] = Date.now().toString();
822
823
console.log('Outgoing request:', config.url);
824
return config;
825
},
826
827
response: (response) => {
828
// Log successful responses
829
console.log(`Response ${response.statusCode}:`, response.data);
830
831
// Handle global response processing
832
if (response.data && response.data.code === 0) {
833
// Extract data from wrapper
834
response.data = response.data.data;
835
}
836
837
return response;
838
},
839
840
responseError: (error) => {
841
// Handle global error scenarios
842
console.error('Request failed:', error);
843
844
// Handle authentication errors
845
if (error.statusCode === 401) {
846
// Redirect to login
847
console.log('Authentication required, redirecting to login');
848
// Clear invalid token
849
removeStorageSync('authToken');
850
}
851
852
// Handle server errors
853
if (error.statusCode >= 500) {
854
showToast({
855
title: 'Server error, please try again',
856
icon: 'error'
857
});
858
}
859
860
throw error;
861
}
862
});
863
864
// Add base URL interceptor
865
addInterceptor({
866
request: (config) => {
867
// Add base URL if not already absolute
868
if (!config.url.startsWith('http')) {
869
const baseURL = getStorageSync('apiBaseURL') || 'https://api.example.com';
870
config.url = `${baseURL}${config.url}`;
871
}
872
return config;
873
}
874
});
875
876
// Add retry interceptor
877
let retryCount = 0;
878
const MAX_RETRIES = 3;
879
880
addInterceptor({
881
responseError: async (error) => {
882
if (retryCount < MAX_RETRIES && error.statusCode >= 500) {
883
retryCount++;
884
console.log(`Retrying request (${retryCount}/${MAX_RETRIES})`);
885
886
// Wait before retry
887
await new Promise(resolve => setTimeout(resolve, 1000 * retryCount));
888
889
// Retry the original request
890
return request(error.config);
891
}
892
893
retryCount = 0; // Reset on final failure
894
throw error;
895
}
896
});
897
898
// Remove all interceptors when needed
899
function resetInterceptors() {
900
cleanInterceptors();
901
console.log('All interceptors removed');
902
}
903
```
904
905
### Advanced Request Patterns
906
907
Complex request scenarios and best practices for common use cases.
908
909
```typescript
910
// File upload simulation (since actual file upload varies by implementation)
911
const uploadFile = async (file: File, uploadUrl: string) => {
912
// Convert file to base64 for transmission
913
const fileData = await new Promise<string>((resolve) => {
914
const reader = new FileReader();
915
reader.onload = () => resolve(reader.result as string);
916
reader.readAsDataURL(file);
917
});
918
919
const response = await request({
920
url: uploadUrl,
921
method: 'POST',
922
data: {
923
filename: file.name,
924
fileType: file.type,
925
fileData: fileData,
926
size: file.size
927
},
928
header: {
929
'Content-Type': 'application/json'
930
},
931
timeout: 30000 // Extended timeout for uploads
932
});
933
934
return response.data;
935
};
936
937
// Batch requests with concurrency control
938
const batchRequests = async <T>(
939
urls: string[],
940
concurrency: number = 3
941
): Promise<T[]> => {
942
const results: T[] = [];
943
944
for (let i = 0; i < urls.length; i += concurrency) {
945
const batch = urls.slice(i, i + concurrency);
946
const batchPromises = batch.map(url =>
947
request({ url, method: 'GET' }).then(res => res.data)
948
);
949
950
const batchResults = await Promise.all(batchPromises);
951
results.push(...batchResults);
952
}
953
954
return results;
955
};
956
957
// Request with timeout and retry
958
const requestWithRetry = async (
959
options: RequestOption,
960
maxRetries: number = 3,
961
retryDelay: number = 1000
962
): Promise<RequestResult> => {
963
let lastError: any;
964
965
for (let attempt = 1; attempt <= maxRetries; attempt++) {
966
try {
967
return await request({
968
...options,
969
timeout: options.timeout || 5000
970
});
971
} catch (error) {
972
lastError = error;
973
974
if (attempt < maxRetries) {
975
console.log(`Request attempt ${attempt} failed, retrying in ${retryDelay}ms`);
976
await new Promise(resolve => setTimeout(resolve, retryDelay));
977
retryDelay *= 2; // Exponential backoff
978
}
979
}
980
}
981
982
throw lastError;
983
};
984
985
// Cached requests with TTL
986
const requestCache = new Map<string, { data: any, timestamp: number, ttl: number }>();
987
988
const cachedRequest = async (
989
options: RequestOption,
990
ttlMs: number = 300000 // 5 minutes default
991
): Promise<RequestResult> => {
992
const cacheKey = `${options.method || 'GET'}:${options.url}:${JSON.stringify(options.data || {})}`;
993
const cached = requestCache.get(cacheKey);
994
995
if (cached && Date.now() - cached.timestamp < cached.ttl) {
996
console.log('Returning cached response for:', options.url);
997
return {
998
data: cached.data,
999
statusCode: 200,
1000
header: {},
1001
cookies: []
1002
};
1003
}
1004
1005
const response = await request(options);
1006
1007
// Cache successful responses
1008
if (response.statusCode >= 200 && response.statusCode < 300) {
1009
requestCache.set(cacheKey, {
1010
data: response.data,
1011
timestamp: Date.now(),
1012
ttl: ttlMs
1013
});
1014
}
1015
1016
return response;
1017
};
1018
```
1019
1020
### Error Handling
1021
1022
Comprehensive error handling patterns for network requests.
1023
1024
```typescript
1025
// Detailed error handling
1026
const handleApiRequest = async (options: RequestOption) => {
1027
try {
1028
const response = await request(options);
1029
1030
// Check for application-level errors
1031
if (response.data && response.data.error) {
1032
throw new Error(`API Error: ${response.data.error.message}`);
1033
}
1034
1035
return response.data;
1036
1037
} catch (error: any) {
1038
// Network or HTTP errors
1039
if (error.statusCode) {
1040
switch (error.statusCode) {
1041
case 400:
1042
throw new Error('Bad request - please check your data');
1043
case 401:
1044
throw new Error('Authentication required');
1045
case 403:
1046
throw new Error('Access forbidden');
1047
case 404:
1048
throw new Error('Resource not found');
1049
case 429:
1050
throw new Error('Too many requests - please wait');
1051
case 500:
1052
throw new Error('Server error - please try again later');
1053
default:
1054
throw new Error(`HTTP ${error.statusCode}: ${error.errMsg || 'Unknown error'}`);
1055
}
1056
}
1057
1058
// Network connectivity errors
1059
if (error.message?.includes('timeout')) {
1060
throw new Error('Request timeout - please check your connection');
1061
}
1062
1063
if (error.message?.includes('network')) {
1064
throw new Error('Network error - please check your connection');
1065
}
1066
1067
// Re-throw unknown errors
1068
throw error;
1069
}
1070
};
1071
1072
// Usage with proper error handling
1073
async function fetchUserProfile(userId: string) {
1074
try {
1075
const profile = await handleApiRequest({
1076
url: `/api/users/${userId}`,
1077
method: 'GET'
1078
});
1079
1080
return profile;
1081
1082
} catch (error) {
1083
console.error('Failed to fetch user profile:', error.message);
1084
1085
// Show user-friendly error message
1086
showToast({
1087
title: error.message || 'Failed to load profile',
1088
icon: 'error'
1089
});
1090
1091
// Return fallback data or re-throw
1092
return null;
1093
}
1094
}
1095
```
1096
1097
### Callback Pattern Support
1098
1099
Traditional callback pattern support alongside Promise-based usage.
1100
1101
```typescript
1102
// Using callbacks instead of promises
1103
request({
1104
url: 'https://api.example.com/data',
1105
method: 'GET',
1106
success: (response) => {
1107
console.log('Success:', response.data);
1108
console.log('Status:', response.statusCode);
1109
},
1110
fail: (error) => {
1111
console.error('Request failed:', error);
1112
},
1113
complete: (result) => {
1114
console.log('Request completed');
1115
// Called regardless of success or failure
1116
}
1117
});
1118
1119
// Mixed usage - callbacks with promise handling
1120
const response = await request({
1121
url: 'https://api.example.com/data',
1122
method: 'POST',
1123
data: { message: 'Hello' },
1124
success: (res) => {
1125
console.log('Callback success:', res.statusCode);
1126
},
1127
fail: (err) => {
1128
console.log('Callback failure:', err);
1129
}
1130
});
1131
1132
console.log('Promise result:', response.data);
1133
```
1134
1135
## Types
1136
1137
```typescript { .api }
1138
type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
1139
type DataType = 'json' | 'text' | 'base64';
1140
type ResponseType = 'text' | 'json' | 'arraybuffer';
1141
1142
interface NetworkError extends Error {
1143
statusCode?: number;
1144
errMsg?: string;
1145
config?: RequestOption;
1146
}
1147
```