@superutils/fetch 1.5.15 → 1.5.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +211 -213
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -14,26 +14,26 @@ For full API reference check out the [docs page](https://alien45.github.io/super
|
|
|
14
14
|
|
|
15
15
|
- [Features](#features)
|
|
16
16
|
- [Installation](#installation)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
- [NPM](#npm)
|
|
18
|
+
- [CDN / Browser](#cdn--browser)
|
|
19
|
+
- [Defaults](#defaults)
|
|
20
|
+
- [Timeout](#timeout)
|
|
21
|
+
- [Conent Type](#content-type)
|
|
22
|
+
- [Response Parsing](#fetch-as)
|
|
23
23
|
- [Usage](#usage)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
24
|
+
- [`fetch()`](#fetch): drop-in replacement for built-in `fetch()`
|
|
25
|
+
- [`TimeoutPromise` Instance](#promise-features): finer control over the request
|
|
26
|
+
- [`Method Specific Functions`](#methods)
|
|
27
|
+
- [`fetch.get()`](#fetch-get)
|
|
28
|
+
- [`fetch.get.deferred()`](#fetch-deferred): cancellable and debounced or throttled `fetch()`
|
|
29
|
+
- [`fetch.post()`](#post): make post requests
|
|
30
|
+
- [`fetch.post.deferred()`](#post-deferred): cancellable and debounced or throttled `post()`
|
|
31
|
+
- [`Interceptors/Transformers`](#interceptors)
|
|
32
|
+
- [`Retry`](#retry) Retry on request failure
|
|
33
|
+
- [`Timeout`](#timeout) Abort request on timeout
|
|
34
|
+
- [`createClient()`](#create-client):
|
|
35
|
+
- [`createPostClient()`](#create-post-client):
|
|
36
|
+
- [`fetchFunc`](#fetch-func): Using with third-party libraries (e.g., Axios)
|
|
37
37
|
|
|
38
38
|
## Features
|
|
39
39
|
|
|
@@ -142,8 +142,8 @@ To retrieve the response in a different format (e.g., as text, a blob, or the ra
|
|
|
142
142
|
import fetch, { FetchAs } from '@superutils/fetch'
|
|
143
143
|
|
|
144
144
|
fetch
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
.get('[DUMMYJSON-DOT-COM]/products/1', { as: FetchAs.text })
|
|
146
|
+
.then(console.log)
|
|
147
147
|
```
|
|
148
148
|
|
|
149
149
|
> **Note:** To ensure type safety, the `as` property is excluded from `fetch.defaults` in TypeScript. Since this option determines the function's return type, setting it globally would prevent accurate type inference for individual requests.
|
|
@@ -160,8 +160,8 @@ Use as a drop-in replacement to built-in `fetch()`.
|
|
|
160
160
|
import fetch from '@superutils/fetch'
|
|
161
161
|
|
|
162
162
|
fetch('[DUMMYJSON-DOT-COM]/products/1')
|
|
163
|
-
|
|
164
|
-
|
|
163
|
+
.then(response => response.json())
|
|
164
|
+
.then(console.log)
|
|
165
165
|
```
|
|
166
166
|
|
|
167
167
|
<div id="promise-features"></div>
|
|
@@ -180,11 +180,11 @@ const request = fetch('[DUMMYJSON-DOT-COM]/products/1')
|
|
|
180
180
|
console.log(request.pending) // true
|
|
181
181
|
|
|
182
182
|
request.then(() => {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
183
|
+
console.log(request.resolved) // true
|
|
184
|
+
console.log(request.pending) // false
|
|
185
|
+
console.log(request.rejected) // false
|
|
186
|
+
console.log(request.aborted) // false
|
|
187
|
+
console.log(request.timedout) // false
|
|
188
188
|
})
|
|
189
189
|
```
|
|
190
190
|
|
|
@@ -201,7 +201,7 @@ request.then(result => console.log(result), console.warn)
|
|
|
201
201
|
// Add a callback to do stuff whenever request is aborted externally.
|
|
202
202
|
// This will not be invoked if fetch fails or resolves (promise finalized naturally) using the Promise executor.
|
|
203
203
|
request.onEarlyFinalize.push((resolved, valueOrReason) =>
|
|
204
|
-
|
|
204
|
+
console.log('Aborted externally:', { resolved, valueOrReason }),
|
|
205
205
|
)
|
|
206
206
|
|
|
207
207
|
// resolve/reject before the promise is finalized
|
|
@@ -261,8 +261,8 @@ Equivalent to `fetch(url, { method: 'get', as: 'json' })`.
|
|
|
261
261
|
import fetch from '@superutils/fetch'
|
|
262
262
|
|
|
263
263
|
fetch
|
|
264
|
-
|
|
265
|
-
|
|
264
|
+
.get('[DUMMYJSON-DOT-COM]/products/1')
|
|
265
|
+
.then(product => console.log({ product }))
|
|
266
266
|
```
|
|
267
267
|
|
|
268
268
|
<div id="fetch-deferred"></div>
|
|
@@ -276,22 +276,22 @@ import fetch from '@superutils/fetch'
|
|
|
276
276
|
|
|
277
277
|
// Create a debounced search function with a 300ms delay.
|
|
278
278
|
const searchProducts = fetch.get.deferred({
|
|
279
|
-
|
|
280
|
-
|
|
279
|
+
delay: 300, // Debounce delay
|
|
280
|
+
resolveIgnored: 'WITH_UNDEFINED', // Ignored (aborted) promises will resolve with `undefined`
|
|
281
281
|
})
|
|
282
282
|
|
|
283
283
|
// User types 'iphone'
|
|
284
284
|
searchProducts('[DUMMYJSON-DOT-COM]/products/search?q=iphone').then(result => {
|
|
285
|
-
|
|
285
|
+
console.log('Result for "iphone":', result)
|
|
286
286
|
})
|
|
287
287
|
|
|
288
288
|
// Before 300ms has passed, the user continues typing 'iphone 12'
|
|
289
289
|
setTimeout(() => {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
290
|
+
searchProducts('[DUMMYJSON-DOT-COM]/products/search?q=iphone 12').then(
|
|
291
|
+
result => {
|
|
292
|
+
console.log('Result for "iphone 12":', result)
|
|
293
|
+
},
|
|
294
|
+
)
|
|
295
295
|
}, 200)
|
|
296
296
|
// Outcome:
|
|
297
297
|
// The first request for "iphone" is aborted.
|
|
@@ -306,18 +306,18 @@ setTimeout(() => {
|
|
|
306
306
|
- **`delay: 0`**: Disables debouncing and throttling, enabling sequential/queue mode. Both requests ("iphone"
|
|
307
307
|
and "iphone 12") would execute, but one after the other, never simultaneously.
|
|
308
308
|
- **`resolveIgnored` (enum)**: Controls how the promise for an aborted request (like the first "iphone" call) resolves.
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
309
|
+
1. `ResolveIgnored.WITH_UNDEFINED` (used in the example): The promise for the aborted "iphone"
|
|
310
|
+
request resolves with `undefined`.
|
|
311
|
+
2. `ResolveIgnored.WITH_LAST`: The promise for the aborted "iphone" request waits and resolves with the result
|
|
312
|
+
of the final "iphone 12" request. Both promises resolve to the same value.
|
|
313
|
+
3. `ResolveIgnored.NEVER`: The promise for the aborted "iphone" request is neither resolved nor rejected.
|
|
314
|
+
It will remain pending indefinitely.
|
|
315
315
|
- **`resolveError` (enum)**: Controls how failed requests are handled.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
316
|
+
1. `ResolveError.NEVER`: The promise for a failed request will neither resolve nor reject, causing it to remain pending indefinitely.
|
|
317
|
+
> **Warning:** Use with caution, as this may lead to memory leaks if not handled properly.
|
|
318
|
+
2. `ResolveError.WITH_ERROR`: The promise resolves with the `FetchError` object instead of being rejected.
|
|
319
|
+
3. `ResolveError.WITH_UNDEFINED`: The promise resolves with an `undefined` value upon failure.
|
|
320
|
+
4. `ResolveError.REJECT`: (Default) The promise is rejected with a `FetchError`, adhering to standard promise behavior.
|
|
321
321
|
|
|
322
322
|
<!-- #### Using defaults to reduce redundancy
|
|
323
323
|
|
|
@@ -361,8 +361,8 @@ import fetch from '@superutils/fetch'
|
|
|
361
361
|
const newProduct = { title: 'Perfume Oil' }
|
|
362
362
|
|
|
363
363
|
fetch.post('[DUMMYJSON-DOT-COM]/products/add', newProduct).then(
|
|
364
|
-
|
|
365
|
-
|
|
364
|
+
createdProduct => console.log('Product created:', createdProduct),
|
|
365
|
+
error => console.error('Failed to create product:', error),
|
|
366
366
|
)
|
|
367
367
|
```
|
|
368
368
|
|
|
@@ -380,13 +380,13 @@ import PromisE from '@superutils/promise'
|
|
|
380
380
|
|
|
381
381
|
// Create a throttled function to auto-save product updates.
|
|
382
382
|
const saveProductThrottled = fetch.post.deferred(
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
383
|
+
{
|
|
384
|
+
delay: 1000, // Throttle window of 1 second
|
|
385
|
+
throttle: true,
|
|
386
|
+
trailing: true, // Ensures the very last update is always saved
|
|
387
|
+
onResult: product => console.log(`[Saved] Product: ${product.title}`),
|
|
388
|
+
},
|
|
389
|
+
'[DUMMYJSON-DOT-COM]/products/add', // Default URL
|
|
390
390
|
)
|
|
391
391
|
// Simulate a user typing quickly, triggering multiple saves.
|
|
392
392
|
console.log('User starts typing...')
|
|
@@ -418,40 +418,40 @@ let currentRefreshToken = ''
|
|
|
418
418
|
// Create a debounced function to refresh the auth token.
|
|
419
419
|
// It waits 300ms after the last call before executing.
|
|
420
420
|
const requestNewToken = fetch.post.deferred(
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
421
|
+
{
|
|
422
|
+
delay: 300, // debounce delay
|
|
423
|
+
onResult: ({ refreshToken = '' }) => {
|
|
424
|
+
console.log(
|
|
425
|
+
`Auth token successfully refreshed at ${new Date().toISOString()}`,
|
|
426
|
+
)
|
|
427
|
+
currentRefreshToken = refreshToken
|
|
428
|
+
},
|
|
429
|
+
},
|
|
430
|
+
'[DUMMYJSON-DOT-COM]/auth/refresh', // Default URL
|
|
431
|
+
() => ({
|
|
432
|
+
refreshToken: currentRefreshToken,
|
|
433
|
+
expiresInMins: 30,
|
|
434
|
+
}),
|
|
435
435
|
)
|
|
436
436
|
|
|
437
437
|
// First authenticate user to get the initial refresh token and then request new refresh tokens
|
|
438
438
|
fetch
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
439
|
+
.post<{ refreshToken: string }>(
|
|
440
|
+
'[DUMMYJSON-DOT-COM]/auth/login',
|
|
441
|
+
{
|
|
442
|
+
username: 'emilys',
|
|
443
|
+
password: 'emilyspass',
|
|
444
|
+
expiresInMins: 30,
|
|
445
|
+
},
|
|
446
|
+
{ credentials: 'include' },
|
|
447
|
+
)
|
|
448
|
+
.then(result => {
|
|
449
|
+
currentRefreshToken = result?.refreshToken
|
|
450
|
+
|
|
451
|
+
requestNewToken() // Called at 0ms
|
|
452
|
+
PromisE.delay(50, requestNewToken) // Called at 50ms
|
|
453
|
+
PromisE.delay(100, requestNewToken) // Called at 100ms
|
|
454
|
+
}, console.error)
|
|
455
455
|
// Outcome:
|
|
456
456
|
// The first two calls are aborted by the debounce mechanism.
|
|
457
457
|
// Only the final call executes, 300ms after it was made (at the 400ms mark).
|
|
@@ -467,8 +467,8 @@ The following interceptor callbacks allow intercepting and/or transforming at di
|
|
|
467
467
|
#### Interceptor types (executed in sequence):
|
|
468
468
|
|
|
469
469
|
1. `request`: Request interceptors are executed before a HTTP request is made.
|
|
470
|
-
|
|
471
|
-
|
|
470
|
+
- To transform the URL simply return a new or modified URL.
|
|
471
|
+
- To transform `fetch` options simply modify the options parameter
|
|
472
472
|
2. `response`: Response interceptors are executed after receiving a `fetch` Response regardless of the HTTP status code.
|
|
473
473
|
3. `result`: Result interceptors are executed before returning the result. To transform the result simply return a new value.
|
|
474
474
|
PS: if the value of `options.as` is `FetchAs.response` (`"response"`), the value received in result will be a `Response` object.
|
|
@@ -480,8 +480,8 @@ The following interceptor callbacks allow intercepting and/or transforming at di
|
|
|
480
480
|
- If an exception is raised while executing the interceptors, it will be gracefully ignored.
|
|
481
481
|
- Value returned (transformed) by an interceptor will be carried over to the subsequent interceptor of the same type.
|
|
482
482
|
- There are 2 category of interceptors:
|
|
483
|
-
|
|
484
|
-
|
|
483
|
+
- Local: interceptors provided when making a request.
|
|
484
|
+
- Global: interceptors that are executed application-wide on every request. Global interceptors can be added/accessed at `fetch.defaults.interceptors`. Global interceptors are always executed before local interceptors.
|
|
485
485
|
|
|
486
486
|
**Example: Interceptor usage**
|
|
487
487
|
|
|
@@ -489,50 +489,48 @@ The following interceptor callbacks allow intercepting and/or transforming at di
|
|
|
489
489
|
import fetch, { FetchError } from '@superutils/fetch'
|
|
490
490
|
|
|
491
491
|
const interceptors = {
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
},
|
|
531
|
-
],
|
|
492
|
+
error: [
|
|
493
|
+
(err, url, options) => {
|
|
494
|
+
console.log('Request failed', err, url, options)
|
|
495
|
+
// return nothing/undefined to keep the error unchanged
|
|
496
|
+
// or return modified/new error
|
|
497
|
+
err.message = 'My custom error message!'
|
|
498
|
+
// or create a new FetchError by cloning it (make sure all the required properties are set correctly)
|
|
499
|
+
return err.clone('My custom error message!')
|
|
500
|
+
},
|
|
501
|
+
],
|
|
502
|
+
request: [
|
|
503
|
+
(url, options) => {
|
|
504
|
+
// add extra headers or modify request options here
|
|
505
|
+
options.headers.append('x-custom-header', 'some value')
|
|
506
|
+
|
|
507
|
+
// transform the URL by returning a modified URL
|
|
508
|
+
return url + '?param=value'
|
|
509
|
+
},
|
|
510
|
+
],
|
|
511
|
+
response: [
|
|
512
|
+
(response, url, options) => {
|
|
513
|
+
if (response.ok) return
|
|
514
|
+
console.log('request was not successful', { url, options })
|
|
515
|
+
|
|
516
|
+
// You can transform the response by returning different `Response` object or even make a completely new HTTP request.
|
|
517
|
+
// The subsequent response interceptors will receive the returned response
|
|
518
|
+
return fetch('[DUMMYJSON-DOT-COM]/products/1') // promise will be resolved automatically
|
|
519
|
+
},
|
|
520
|
+
],
|
|
521
|
+
result: [
|
|
522
|
+
(result, url, options) => {
|
|
523
|
+
const productId = Number(new URL(url).pathname.split('/products/')[1])
|
|
524
|
+
if (options.method === 'get' && !Number.isNaN(productId)) {
|
|
525
|
+
result.title ??= 'Unknown title'
|
|
526
|
+
}
|
|
527
|
+
return result
|
|
528
|
+
},
|
|
529
|
+
],
|
|
532
530
|
}
|
|
533
531
|
fetch
|
|
534
|
-
|
|
535
|
-
|
|
532
|
+
.get('[DUMMYJSON-DOT-COM]/products/1', { interceptors })
|
|
533
|
+
.then(product => console.log({ product }))
|
|
536
534
|
```
|
|
537
535
|
|
|
538
536
|
**Example: Add global request and error interceptors**
|
|
@@ -543,14 +541,14 @@ import fetch from '@superutils/fetch'
|
|
|
543
541
|
const { interceptors } = fetch.defaults
|
|
544
542
|
|
|
545
543
|
interceptors.request.push((url, options) => {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
544
|
+
// a headers to all requests make by the application
|
|
545
|
+
// add headers to all requests made by the application
|
|
546
|
+
options.headers.append('x-auth', 'token')
|
|
549
547
|
})
|
|
550
548
|
|
|
551
549
|
interceptors.error.push((err, url, options) => {
|
|
552
|
-
|
|
553
|
-
|
|
550
|
+
// log whenever a request fails
|
|
551
|
+
console.log('Error interceptor', err)
|
|
554
552
|
})
|
|
555
553
|
|
|
556
554
|
// Each time a requst is made using @superutils/fetch, the above interceptors will be executed when appropriate
|
|
@@ -567,12 +565,12 @@ The `retry` option provides a robust mechanism to automatically re-attempt faile
|
|
|
567
565
|
import fetch from '@superutils/fetch'
|
|
568
566
|
|
|
569
567
|
fetch
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
568
|
+
.get('[DUMMYJSON-DOT-COM]/products/1', {
|
|
569
|
+
retry: 3, // If request fails, retry up to three more times
|
|
570
|
+
// Retry on rate limits (429) or transient server errors (5xx).
|
|
571
|
+
retryIf: r => r.status === 429 || r.status >= 500,
|
|
572
|
+
})
|
|
573
|
+
.then(console.log)
|
|
576
574
|
```
|
|
577
575
|
|
|
578
576
|
<div id="create-client"></div>
|
|
@@ -588,42 +586,42 @@ import { createClient } from '@superutils/fetch'
|
|
|
588
586
|
|
|
589
587
|
// Create a "GET" client with default headers and a 5-second timeout
|
|
590
588
|
const apiClient = createClient(
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
589
|
+
{
|
|
590
|
+
// fixed options (cannot be overridden)
|
|
591
|
+
method: 'get',
|
|
592
|
+
},
|
|
593
|
+
{
|
|
594
|
+
// common options (can be overridden)
|
|
595
|
+
headers: {
|
|
596
|
+
Authorization: 'Bearer my-secret-token',
|
|
597
|
+
'Content-Type': 'application/json',
|
|
598
|
+
},
|
|
599
|
+
timeout: 5000,
|
|
600
|
+
},
|
|
601
|
+
{
|
|
602
|
+
// defer options (can be overridden)
|
|
603
|
+
delay: 300,
|
|
604
|
+
retry: 2, // If request fails, retry up to two more times
|
|
605
|
+
},
|
|
608
606
|
)
|
|
609
607
|
|
|
610
608
|
// Use it just like the standard fetch
|
|
611
609
|
apiClient('[DUMMYJSON-DOT-COM]/products/1', {
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
610
|
+
// The 'method' property cannot be overridden as it is used in the fixed options when creating the client.
|
|
611
|
+
// In TypeScript, the compiler will not allow this property.
|
|
612
|
+
// In Javascript, it will simply be ignored.
|
|
613
|
+
// method: 'post',
|
|
614
|
+
timeout: 3000, // The 'timeout' property can be overridden
|
|
617
615
|
}).then(console.log, console.warn)
|
|
618
616
|
|
|
619
617
|
// create a deferred client using "apiClient"
|
|
620
618
|
const deferredClient = apiClient.deferred(
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
619
|
+
{ retry: 0 }, // disable retrying by overriding the `retry` defer option
|
|
620
|
+
'[DUMMYJSON-DOT-COM]/products/1',
|
|
621
|
+
{ timeout: 3000 },
|
|
624
622
|
)
|
|
625
623
|
deferredClient({ timeout: 10000 }) // timeout is overridden by individual request
|
|
626
|
-
|
|
624
|
+
.then(console.log, console.warn)
|
|
627
625
|
```
|
|
628
626
|
|
|
629
627
|
<div id="create-post-client"></div>
|
|
@@ -639,36 +637,36 @@ import { createPostClient } from '@superutils/fetch'
|
|
|
639
637
|
|
|
640
638
|
// Create a POST client with 10-second as the default timeout
|
|
641
639
|
const postClient = createPostClient(
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
640
|
+
{
|
|
641
|
+
headers: { 'content-type': 'application/json' },
|
|
642
|
+
},
|
|
643
|
+
{
|
|
644
|
+
method: 'post',
|
|
645
|
+
timeout: 10000,
|
|
646
|
+
},
|
|
649
647
|
)
|
|
650
648
|
|
|
651
649
|
// Invoking `postClient()` automatically applies the pre-configured options
|
|
652
650
|
postClient(
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
651
|
+
'[DUMMYJSON-DOT-COM]/products/add',
|
|
652
|
+
{ title: 'New Product' }, // data/body
|
|
653
|
+
{}, // other options
|
|
656
654
|
).then(result => console.log('Product created:', result))
|
|
657
655
|
|
|
658
656
|
// create a deferred client using "postClient"
|
|
659
657
|
const deferredPatchClient = postClient.deferred(
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
658
|
+
{
|
|
659
|
+
delay: 300,
|
|
660
|
+
// prints only successful results
|
|
661
|
+
onResult: result =>
|
|
662
|
+
console.log('Product updated using deferred function:', result),
|
|
663
|
+
},
|
|
664
|
+
'[DUMMYJSON-DOT-COM]/products/add',
|
|
665
|
+
undefined, // data to be provided later
|
|
666
|
+
{
|
|
667
|
+
method: 'patch', // default method for deferredPatchClient
|
|
668
|
+
timeout: 3000,
|
|
669
|
+
},
|
|
672
670
|
)
|
|
673
671
|
deferredPatchClient({ title: 'New title 1' }) // ignored by debounce
|
|
674
672
|
deferredPatchClient({ title: 'New title 2' }) // executed
|
|
@@ -682,29 +680,29 @@ The `fetchFunc` option allows you to replace the default request engine. This en
|
|
|
682
680
|
|
|
683
681
|
```typescript
|
|
684
682
|
import fetch, {
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
683
|
+
FetchCustomOptions,
|
|
684
|
+
FetchFunc,
|
|
685
|
+
FetchOptions,
|
|
688
686
|
} from '@superutils/fetch'
|
|
689
687
|
import axios from 'axios'
|
|
690
688
|
|
|
691
689
|
type Product = {
|
|
692
|
-
|
|
693
|
-
|
|
690
|
+
id: number
|
|
691
|
+
title: string
|
|
694
692
|
}
|
|
695
693
|
fetch
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
694
|
+
.get<{ data: Product }>('[DUMMYJSON-DOT-COM]/products/1', {
|
|
695
|
+
/**
|
|
696
|
+
* Note: Ensure request options are compatible with the third-party
|
|
697
|
+
* engine's configuration schema.
|
|
698
|
+
*
|
|
699
|
+
* Check {@link FetchOptions} (includes `FetchCustomOptions`).
|
|
700
|
+
*/
|
|
701
|
+
fetchFunc: axios as FetchFunc,
|
|
702
|
+
|
|
703
|
+
// if request fails retry maximus 3 more times
|
|
704
|
+
retry: 3,
|
|
705
|
+
// ...additional options
|
|
706
|
+
})
|
|
707
|
+
.then(({ data }) => console.log({ product: data }))
|
|
710
708
|
```
|
package/package.json
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
},
|
|
6
6
|
"description": "A lightweight `fetch` wrapper for browsers and Node.js, designed to simplify data fetching and reduce boilerplate.",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@superutils/core": "^1.2.
|
|
9
|
-
"@superutils/promise": "^1.3.
|
|
8
|
+
"@superutils/core": "^1.2.15",
|
|
9
|
+
"@superutils/promise": "^1.3.14"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist",
|
|
@@ -53,6 +53,6 @@
|
|
|
53
53
|
"module": "./dist/index.js",
|
|
54
54
|
"type": "module",
|
|
55
55
|
"types": "./dist/index.d.ts",
|
|
56
|
-
"version": "1.5.
|
|
57
|
-
"gitHead": "
|
|
56
|
+
"version": "1.5.16",
|
|
57
|
+
"gitHead": "7be3be6fb4a8cb1955ee5f704fc49bbb792bd961"
|
|
58
58
|
}
|