@@ -8,117 +8,98 @@ const inFlightMap = new Map();
8
8
* Generate a signature for dedup if deduplicate is true
9
9
*/
10
10
function makeSignature ( input , init ) {
11
- // Basic approach:
12
- const normalized = {
13
- url : typeof input === "string" ? input : input . url ,
14
- method : init ?. method ?? "GET" ,
15
- headers : init ?. headers ?? { } ,
16
- body : init ?. body ?? null ,
17
- } ;
18
- return JSON . stringify ( normalized ) ;
11
+ // Basic approach:
12
+ const normalized = {
13
+ url : typeof input === "string" ? input : input . url ,
14
+ method : init ?. method ?? "GET" ,
15
+ headers : init ?. headers ?? { } ,
16
+ body : init ?. body ?? null ,
17
+ } ;
18
+ return JSON . stringify ( normalized ) ;
19
19
}
20
20
/**
21
21
* Sleep helper for retryDelay
22
22
*/
23
23
function sleep ( ms ) {
24
- return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
24
+ return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
25
25
}
26
26
/**
27
27
* FastFetch main function
28
28
* - Retries on error with exponential backoff
29
29
* - Deduplicates in-flight requests if deduplicate = true
30
30
*/
31
31
export async function fastFetch ( input , init ) {
32
- const {
33
- retries = 0 ,
34
- retryDelay = 1000 ,
35
- deduplicate = true ,
36
- shouldRetry,
37
- } = init || { } ;
38
- console . log ( "[FastFetch] Starting request for:" , input ) ;
39
- // If deduplicating, check if a matching in-flight request exists
40
- let signature = "" ;
41
- if ( deduplicate ) {
42
- signature = makeSignature ( input , init ) ;
43
- if ( inFlightMap . has ( signature ) ) {
44
- console . log (
45
- "[FastFetch] Found in-flight request for signature:" ,
46
- signature ,
47
- ) ;
48
- return inFlightMap . get ( signature ) ;
49
- }
50
- }
51
- // Build a promise chain that tries up to retries + 1 times with exponential backoff
52
- let attempt = 0 ;
53
- let promise = ( async function fetchWithRetry ( ) {
54
- while ( true ) {
55
- try {
56
- attempt ++ ;
57
- console . log ( `[FastFetch] Attempt #${ attempt } for:` , input ) ;
58
- const response = await fetch ( input , init ) ;
59
- if ( ! response . ok && shouldRetry ) {
60
- const doRetry = shouldRetry ( response , attempt ) ;
61
- console . log (
62
- `[FastFetch] Response not ok (status: ${ response . status } ). Retry decision: ${ doRetry } ` ,
63
- ) ;
64
- if ( doRetry && attempt <= retries ) {
65
- const delay = retryDelay * Math . pow ( 2 , attempt - 1 ) ;
66
- console . log (
67
- `[FastFetch] Waiting ${ delay } ms (exponential backoff) before retrying...` ,
68
- ) ;
69
- await sleep ( delay ) ;
70
- continue ; // try again
71
- }
72
- }
73
- console . log ( `[FastFetch] Request succeeded on attempt #${ attempt } ` ) ;
74
- return response ;
75
- } catch ( error ) {
76
- console . log ( `[FastFetch] Caught error on attempt #${ attempt } :` , error ) ;
77
- if ( shouldRetry ) {
78
- const doRetry = shouldRetry ( error , attempt ) ;
79
- console . log ( `[FastFetch] Retry decision based on error: ${ doRetry } ` ) ;
80
- if ( doRetry && attempt <= retries ) {
81
- const delay = retryDelay * Math . pow ( 2 , attempt - 1 ) ;
82
- console . log (
83
- `[FastFetch] Waiting ${ delay } ms (exponential backoff) before retrying after error...` ,
84
- ) ;
85
- await sleep ( delay ) ;
86
- continue ;
87
- }
88
- } else {
89
- if ( attempt <= retries ) {
90
- const delay = retryDelay * Math . pow ( 2 , attempt - 1 ) ;
91
- console . log (
92
- `[FastFetch] Retrying attempt #${ attempt } after error. Waiting ${ delay } ms...` ,
93
- ) ;
94
- await sleep ( delay ) ;
95
- continue ;
96
- }
32
+ const { retries = 0 , retryDelay = 1000 , deduplicate = true , shouldRetry, } = init || { } ;
33
+ console . log ( "[FastFetch] Starting request for:" , input ) ;
34
+ // If deduplicating, check if a matching in-flight request exists
35
+ let signature = "" ;
36
+ if ( deduplicate ) {
37
+ signature = makeSignature ( input , init ) ;
38
+ if ( inFlightMap . has ( signature ) ) {
39
+ console . log ( "[FastFetch] Found in-flight request for signature:" , signature ) ;
40
+ return inFlightMap . get ( signature ) ;
97
41
}
98
- console . log ( "[FastFetch] No more retries. Throwing error." ) ;
99
- throw error ;
100
- }
101
42
}
102
- } ) ( ) ;
103
- // If deduplicating, store in the map so subsequent calls get the same promise
104
- if ( deduplicate ) {
105
- inFlightMap . set ( signature , promise ) ;
106
- console . log (
107
- "[FastFetch] Stored in-flight request with signature:" ,
108
- signature ,
109
- ) ;
110
- }
111
- try {
112
- const result = await promise ;
113
- return result ;
114
- } finally {
115
- // Once done (success or fail), remove from inFlightMap
43
+ // Build a promise chain that tries up to retries + 1 times with exponential backoff
44
+ let attempt = 0 ;
45
+ let promise = ( async function fetchWithRetry ( ) {
46
+ while ( true ) {
47
+ try {
48
+ attempt ++ ;
49
+ console . log ( `[FastFetch] Attempt #${ attempt } for:` , input ) ;
50
+ const response = await fetch ( input , init ) ;
51
+ if ( ! response . ok && shouldRetry ) {
52
+ const doRetry = shouldRetry ( response , attempt ) ;
53
+ console . log ( `[FastFetch] Response not ok (status: ${ response . status } ). Retry decision: ${ doRetry } ` ) ;
54
+ if ( doRetry && attempt <= retries ) {
55
+ const delay = retryDelay * Math . pow ( 2 , attempt - 1 ) ;
56
+ console . log ( `[FastFetch] Waiting ${ delay } ms (exponential backoff) before retrying...` ) ;
57
+ await sleep ( delay ) ;
58
+ continue ; // try again
59
+ }
60
+ }
61
+ console . log ( `[FastFetch] Request succeeded on attempt #${ attempt } ` ) ;
62
+ return response ;
63
+ }
64
+ catch ( error ) {
65
+ console . log ( `[FastFetch] Caught error on attempt #${ attempt } :` , error ) ;
66
+ if ( shouldRetry ) {
67
+ const doRetry = shouldRetry ( error , attempt ) ;
68
+ console . log ( `[FastFetch] Retry decision based on error: ${ doRetry } ` ) ;
69
+ if ( doRetry && attempt <= retries ) {
70
+ const delay = retryDelay * Math . pow ( 2 , attempt - 1 ) ;
71
+ console . log ( `[FastFetch] Waiting ${ delay } ms (exponential backoff) before retrying after error...` ) ;
72
+ await sleep ( delay ) ;
73
+ continue ;
74
+ }
75
+ }
76
+ else {
77
+ if ( attempt <= retries ) {
78
+ const delay = retryDelay * Math . pow ( 2 , attempt - 1 ) ;
79
+ console . log ( `[FastFetch] Retrying attempt #${ attempt } after error. Waiting ${ delay } ms...` ) ;
80
+ await sleep ( delay ) ;
81
+ continue ;
82
+ }
83
+ }
84
+ console . log ( "[FastFetch] No more retries. Throwing error." ) ;
85
+ throw error ;
86
+ }
87
+ }
88
+ } ) ( ) ;
89
+ // If deduplicating, store in the map so subsequent calls get the same promise
116
90
if ( deduplicate ) {
117
- inFlightMap . delete ( signature ) ;
118
- console . log (
119
- "[FastFetch] Removed in-flight record for signature:" ,
120
- signature ,
121
- ) ;
91
+ inFlightMap . set ( signature , promise ) ;
92
+ console . log ( "[FastFetch] Stored in-flight request with signature:" , signature ) ;
93
+ }
94
+ try {
95
+ const result = await promise ;
96
+ return result ;
97
+ }
98
+ finally {
99
+ // Once done (success or fail), remove from inFlightMap
100
+ if ( deduplicate ) {
101
+ inFlightMap . delete ( signature ) ;
102
+ console . log ( "[FastFetch] Removed in-flight record for signature:" , signature ) ;
103
+ }
122
104
}
123
- }
124
105
}
0 commit comments