@ndriadev/futurable 2.3.2 → 2.3.5
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/CHANGELOG.md +52 -0
- package/README.md +194 -549
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +255 -0
- package/dist/index.d.mts +255 -0
- package/dist/index.d.ts +10 -9
- package/dist/index.mjs +1 -0
- package/package.json +41 -39
- package/dist/example/index.d.ts +0 -2
- package/dist/example/index.d.ts.map +0 -1
- package/dist/futurable.cjs +0 -1
- package/dist/futurable.mjs +0 -437
- package/dist/index.d.ts.map +0 -1
- package/dist/index.test.d.ts +0 -2
- package/dist/index.test.d.ts.map +0 -1
- package/scripts/copy-resources.js +0 -37
- package/scripts/preInstall.js +0 -17
- package/scripts/server.js +0 -16
package/README.md
CHANGED
|
@@ -1,643 +1,288 @@
|
|
|
1
|
-
<h1 align="center">
|
|
2
|
-
<br>
|
|
3
|
-
<a href="https://futurable.ndria.dev/">
|
|
4
|
-
<img src="https://futurable.ndria.dev/Futurable.png" alt="logo">
|
|
5
|
-
</a>
|
|
6
|
-
<br>
|
|
7
|
-
Futurable
|
|
8
|
-
<br>
|
|
9
|
-
</h1>
|
|
10
|
-
|
|
11
|
-
<h3 align="center">Javascript's Promise and Fetch API with super powers!</h3>
|
|
12
|
-
|
|
13
1
|
<div align="center">
|
|
2
|
+
<br>
|
|
3
|
+
<a href="https://futurable.ndria.dev/">
|
|
4
|
+
<img src="https://futurable.ndria.dev/Futurable.png" alt="Futurable Logo" width="200">
|
|
5
|
+
</a>
|
|
6
|
+
<br>
|
|
7
|
+
<h1>Futurable</h1>
|
|
8
|
+
<p><strong>JavaScript's Promise and Fetch APIs with superpowers! 🚀</strong></p>
|
|
9
|
+
|
|
10
|
+
[](https://www.npmjs.org/package/%40ndriadev/futurable)
|
|
11
|
+

|
|
12
|
+

|
|
13
|
+

|
|
14
|
+
|
|
15
|
+

|
|
16
|
+

|
|
17
|
+

|
|
18
|
+

|
|
14
19
|
|
|
15
|
-
[](https://www.npmjs.org/package/%40ndriadev/futurable)
|
|
16
|
-

|
|
17
|
-

|
|
18
|
-

|
|
19
20
|
</div>
|
|
20
|
-
<div align="center">
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-

|
|
25
|
-

|
|
26
|
-
</div>
|
|
22
|
+
---
|
|
23
|
+
## 📋 Table of Contents
|
|
27
24
|
|
|
25
|
+
- [Documentation](https://futurable.ndria.dev/)
|
|
26
|
+
- [About](#-about)
|
|
27
|
+
- [Quick Start](#-quick-start)
|
|
28
|
+
- [Features](#-key-features)
|
|
29
|
+
- [Examples](#-examples)
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
- [Introduction](#introduction)
|
|
31
|
-
- [Installation](#Installation)
|
|
32
|
-
- [Usage](#Usage)
|
|
33
|
-
- [Use-case](#Use-case)
|
|
34
|
-
- [React](#React)
|
|
35
|
-
- [API](#API)
|
|
36
|
-
- [constructor](#constructor)
|
|
37
|
-
- [cancel](#cancel)
|
|
38
|
-
- [onCancel](#oncancelcb-callback)
|
|
39
|
-
- [sleep](#sleeptimer-number)
|
|
40
|
-
- [delay](#delaycb-callback-timer-number)
|
|
41
|
-
- [fetch](#fetchurl-string--val--string-opts-object--requestinit)
|
|
42
|
-
- [futurizable](#futurizablepromise-promise--val--promise)
|
|
43
|
-
- [Futurable.onCancel](#futurableoncancelcb-callback--cb-callback-signal-abortsignal)
|
|
44
|
-
- [Futurable.sleep](#futurablesleeptimer-number--timer-number-signal-abortsignal)
|
|
45
|
-
- [Futurable.delay](#futurabledelaycb-callback-timer-number-signal-abortsignal)
|
|
46
|
-
- [Futurable.fetch](#futurablefetchurl-string-opts-object--requestinit)
|
|
47
|
-
- [Futurable.futurizable](#futurablefuturizablepromise-promise-signal-abortsignal)
|
|
48
|
-
- [Futurable.all](#futurableallvalues-t-signal-abortsignal)
|
|
49
|
-
- [Futurable.allSettled](#futurableallsettledvalues-t-signal-abortsignal)
|
|
50
|
-
- [Futurable.any](#futurableanyvalues-t-signal-abortsignal)
|
|
51
|
-
- [Futurable.race](#futurableracevalues-t-signal-abortsignal)
|
|
52
|
-
- [Futurable.polling](#futurablepollingvalue--futurable--interval-signal-immediate-interval-number-signal-abortsignal-immediate-boolean)
|
|
53
|
-
- [Futurable.withResolvers](#futurablewithresolverssignal-abortsignal)
|
|
54
|
-
- [ToDo](#TODO)
|
|
55
|
-
- [License](#License)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
# Introduction
|
|
59
|
-
Futurable is a library that extends Javascript's Promise and Fetch APIs, adding a number of useful features and with support for Typescirpt. It can be used on both browser and node.
|
|
60
|
-
|
|
61
|
-
Often it happens where to develop a feature using promises that covers a particular need. Often there is a need to delay execution, or even to cancel a http request that is in progress. Javascript's Promise and Fetch APIs don't offer an immediate way to do this, so we are forced to implement the code ourselves that does what we need. The purpose of this library is to provide these features ready to use, without the user having to think about anything else.
|
|
62
|
-
|
|
63
|
-
:warning: If you intend to use the library in node in order to use fetch implementation, for versions lower than **17.5.0** it is necessary to install the *node-fetch* library, since the native support for the Fetch API was introduced by this version.
|
|
64
|
-
|
|
65
|
-
## Installation
|
|
66
|
-
```bash
|
|
31
|
+
---
|
|
67
32
|
|
|
68
|
-
|
|
33
|
+
## 📖 About
|
|
69
34
|
|
|
70
|
-
|
|
35
|
+
**Futurable** is a powerful TypeScript library that extends JavaScript's native `Promise` and `Fetch` APIs with advanced features like **cancellation**, **delays**, **polling**, and more. Built for both browser and Node.js environments, it provides an intuitive API to handle async operations with greater control.
|
|
71
36
|
|
|
72
|
-
|
|
73
|
-
The library supports both ESM and CJS formats, so it can be used as follows:
|
|
74
|
-
```javascript
|
|
75
|
-
import { Futurable } from '@ndriadev/futurable'; // ok
|
|
37
|
+
### Why Futurable?
|
|
76
38
|
|
|
77
|
-
|
|
78
|
-
```
|
|
39
|
+
JavaScript's Promise API is powerful but lacks some crucial features for modern applications:
|
|
79
40
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
```jsx
|
|
86
|
-
export default function Component() {
|
|
87
|
-
//...code
|
|
88
|
-
|
|
89
|
-
useEffect(() => {
|
|
90
|
-
let f;
|
|
91
|
-
function callApi() {
|
|
92
|
-
f = Futurable
|
|
93
|
-
.fetch("...")
|
|
94
|
-
.then(resp => resp.json())
|
|
95
|
-
.then(setTodo);
|
|
96
|
-
}
|
|
97
|
-
callApi();
|
|
98
|
-
return () => {
|
|
99
|
-
f && f.cancel();
|
|
100
|
-
}
|
|
101
|
-
},[])
|
|
102
|
-
|
|
103
|
-
//OR
|
|
104
|
-
|
|
105
|
-
useEffect(() => {
|
|
106
|
-
const controller = new AbortController();
|
|
107
|
-
Futurable
|
|
108
|
-
.fetch(
|
|
109
|
-
"...",
|
|
110
|
-
{
|
|
111
|
-
signal: controller.signal
|
|
112
|
-
}
|
|
113
|
-
)
|
|
114
|
-
.then(resp => resp.json())
|
|
115
|
-
.then(setTodo);
|
|
116
|
-
|
|
117
|
-
return () => {
|
|
118
|
-
controller.abort();
|
|
119
|
-
}
|
|
120
|
-
},[])
|
|
121
|
-
|
|
122
|
-
//...code
|
|
123
|
-
}
|
|
124
|
-
```
|
|
41
|
+
- ❌ No way to cancel pending promises
|
|
42
|
+
- ❌ No built-in delay or sleep functionality
|
|
43
|
+
- ❌ Fetch API doesn't support request cancellation easily
|
|
44
|
+
- ❌ No polling mechanism out of the box
|
|
45
|
+
- ❌ Complex AbortController boilerplate
|
|
125
46
|
|
|
47
|
+
**Futurable solves all of these problems** with a clean, Promise-compatible API that feels natural to use.
|
|
126
48
|
|
|
127
|
-
|
|
128
|
-
The methods implemented, excluding those that are by nature static can be used:
|
|
129
|
-
- During the construction of the futurable using the ***new*** operator;
|
|
130
|
-
- In the chain-style ***promise chaining***.
|
|
131
|
-
|
|
132
|
-
They are the following:
|
|
133
|
-
- [cancel](#cancel)
|
|
134
|
-
- [onCancel](#oncancelcb-callback)
|
|
135
|
-
- [sleep](#sleeptimer-number)
|
|
136
|
-
- [delay](#delaycb-callback-timer-number)
|
|
137
|
-
- [fetch](#fetchurl-string--val--string-opts-object--requestinit)
|
|
138
|
-
- [futurizable](#futurizablepromise-promise--val--promise)
|
|
139
|
-
- [Futurable.onCancel](#futurableoncancelcb-callback--cb-callback-signal-abortsignal)
|
|
140
|
-
- [Futurable.sleep](#futurablesleeptimer-number--timer-number-signal-abortsignal)
|
|
141
|
-
- [Futurable.delay](#futurabledelaycb-callback-timer-number-signal-abortsignal)
|
|
142
|
-
- [Futurable.fetch](#futurablefetchurl-string-opts-object--requestinit)
|
|
143
|
-
- [Futurable.futurizable](#futurablefuturizablepromise-promise-signal-abortsignal)
|
|
144
|
-
- [Futurable.all](#futurableallvalues-t-signal-abortsignal)
|
|
145
|
-
- [Futurable.allSettled](#futurableallsettledvalues-t-signal-abortsignal)
|
|
146
|
-
- [Futurable.any](#futurableanyvalues-t-signal-abortsignal)
|
|
147
|
-
- [Futurable.race](#futurableracevalues-t-signal-abortsignal)
|
|
148
|
-
- [Futurable.polling](#futurablepollingvalue--futurable--interval-signal-immediate-interval-number-signal-abortsignal-immediate-boolean)
|
|
149
|
-
- [Futurable.withResolvers](#futurablewithresolverssignal-abortsignal)
|
|
150
|
-
|
|
151
|
-
### constructor(executor: FuturableExecutor<T>, signal?: AbortSignal)
|
|
152
|
-
Futurable is instantiable like a classic Promise.
|
|
153
|
-
```javascript
|
|
154
|
-
//Javascript Promise
|
|
155
|
-
|
|
156
|
-
const promise = new Promise((resolve, reject) => {
|
|
157
|
-
const data = /*..async operations or other..*/
|
|
158
|
-
resolve(data);
|
|
159
|
-
});
|
|
49
|
+
---
|
|
160
50
|
|
|
161
|
-
|
|
162
|
-
import { Futurable } from '@ndriadev/futurable';
|
|
51
|
+
## ✨ Key Features
|
|
163
52
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
53
|
+
- ✅ **Full Promise Compatibility** - Works as a drop-in replacement for native Promises
|
|
54
|
+
- ✅ **Cancellable Operations** - Cancel any async operation with ease
|
|
55
|
+
- ✅ **Fetch Integration** - Built-in cancellable fetch with AbortController support
|
|
56
|
+
- ✅ **Delays & Sleep** - Add delays without complex setTimeout logic
|
|
57
|
+
- ✅ **Polling Support** - Built-in polling mechanism with cancellation
|
|
58
|
+
- ✅ **TypeScript First** - Full type safety with excellent IDE support
|
|
59
|
+
- ✅ **Tree-shakeable** - Import only what you need
|
|
60
|
+
- ✅ **Zero Dependencies** - Lightweight and fast
|
|
61
|
+
- ✅ **Universal** - Works in Node.js and all modern browsers
|
|
62
|
+
- ✅ **100% Test Coverage** - Battle-tested and reliable
|
|
170
63
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
```javascript
|
|
174
|
-
const controller = new AbortController();
|
|
175
|
-
|
|
176
|
-
const futurable = new Futurable((resolve, reject) => {
|
|
177
|
-
const data = /*..async operations or other..*/
|
|
178
|
-
resolve(data);
|
|
179
|
-
}, controller.signal);
|
|
180
|
-
```
|
|
64
|
+
---
|
|
181
65
|
|
|
182
|
-
|
|
66
|
+
## 🚀 Quick Start
|
|
183
67
|
|
|
184
|
-
|
|
185
|
-
const controller = new AbortController();
|
|
186
|
-
|
|
187
|
-
const futurable = new Futurable((resolve, reject, utils) => {
|
|
188
|
-
const data = /*..async operations or other..*/
|
|
189
|
-
resolve(data);
|
|
190
|
-
});
|
|
191
|
-
```
|
|
192
|
-
Utils is an object with the following properties which mirror the methods described in the usage section and which will be described below:
|
|
193
|
-
- cancel;
|
|
194
|
-
- onCancel:
|
|
195
|
-
- delay;
|
|
196
|
-
- sleep;
|
|
197
|
-
- fetch;
|
|
198
|
-
- futurizable.
|
|
199
|
-
|
|
200
|
-
In addition is has:
|
|
201
|
-
- signal: internal futurable signal;
|
|
202
|
-
|
|
203
|
-
### cancel(): void
|
|
204
|
-
If invoked, it cancel the futurable if it is to be executed or if it is still executing.
|
|
205
|
-
|
|
206
|
-
*Example*
|
|
207
|
-
```javascript
|
|
208
|
-
function asynchronousOperation() {
|
|
209
|
-
return new Futurable((res, rej) => {
|
|
210
|
-
// asynchornous code..
|
|
211
|
-
resolve(true);
|
|
212
|
-
});
|
|
213
|
-
);
|
|
214
|
-
|
|
215
|
-
//...code
|
|
216
|
-
|
|
217
|
-
const futurable = asynchronousOperation();
|
|
218
|
-
futurable.then(value => {
|
|
219
|
-
//DO anything
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
//...code
|
|
223
|
-
|
|
224
|
-
futurable.cancel();
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
### onCancel(cb: callback): void
|
|
228
|
-
If it is invoked, when the futurable is cancelled, it executes the callback passed as a parameter.
|
|
229
|
-
|
|
230
|
-
*Example*
|
|
231
|
-
```javascript
|
|
232
|
-
const futurable = new Futurable((resolve, reject, utils) => {
|
|
233
|
-
utils.onCancel(() => console.log("Futurable cancelled"));
|
|
234
|
-
const data = /*..async operations or other..*/
|
|
235
|
-
resolve(data);
|
|
236
|
-
});
|
|
68
|
+
### Installation
|
|
237
69
|
|
|
238
|
-
//...code
|
|
239
|
-
|
|
240
|
-
futurable.cancel();
|
|
241
|
-
|
|
242
|
-
//OR
|
|
243
|
-
|
|
244
|
-
const futurable = new Futurable((res, rej) => {
|
|
245
|
-
// asynchornous code..
|
|
246
|
-
resolve(true);
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
//...code
|
|
250
|
-
|
|
251
|
-
futurable
|
|
252
|
-
.onCancel(() => console.log("Futurable cancelled"))
|
|
253
|
-
.then(val => .......);
|
|
254
|
-
|
|
255
|
-
//...code
|
|
256
|
-
|
|
257
|
-
futurable.cancel();
|
|
258
|
-
```
|
|
259
70
|
```bash
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
### sleep(timer: number): Futurable<T>
|
|
264
|
-
Waits for timer parameter (in milliseconds) before returning the value.
|
|
265
|
-
|
|
266
|
-
*Example*
|
|
267
|
-
```javascript
|
|
268
|
-
const futurable = new Futurable((resolve, reject, utils) => {
|
|
269
|
-
const data = /*..async operations or other..*/
|
|
270
|
-
utils.sleep(3000);
|
|
271
|
-
resolve(data);
|
|
272
|
-
});
|
|
273
|
-
//...code
|
|
274
|
-
|
|
275
|
-
//OR
|
|
276
|
-
|
|
277
|
-
const futurable = new Futurable((res, rej) => {
|
|
278
|
-
// asynchornous code..
|
|
279
|
-
resolve(true);
|
|
280
|
-
});
|
|
71
|
+
# npm
|
|
72
|
+
npm install @ndriadev/futurable
|
|
281
73
|
|
|
282
|
-
|
|
74
|
+
# yarn
|
|
75
|
+
yarn add @ndriadev/futurable
|
|
283
76
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
.then(val => .......);
|
|
287
|
-
|
|
288
|
-
//...code
|
|
77
|
+
# pnpm
|
|
78
|
+
pnpm add @ndriadev/futurable
|
|
289
79
|
```
|
|
290
80
|
|
|
291
|
-
###
|
|
292
|
-
Waits for timer parameter (in milliseconds), then executes callback with the futurable value and returns the result obtained from the invocation. Callback parameter, when delay is invoked as class method, has the value of futurable, like then method.
|
|
293
|
-
|
|
294
|
-
*Example*
|
|
295
|
-
```javascript
|
|
296
|
-
const futurable = new Futurable((resolve, reject, utils) => {
|
|
297
|
-
const data = /*..async operations or other..*/
|
|
298
|
-
utils.delay(()=>console.log("delayed"), 3000);
|
|
299
|
-
resolve(data);
|
|
300
|
-
});
|
|
81
|
+
### Basic Usage
|
|
301
82
|
|
|
302
|
-
|
|
83
|
+
```typescript
|
|
84
|
+
import { Futurable } from '@ndriadev/futurable';
|
|
303
85
|
|
|
304
|
-
//
|
|
86
|
+
// Create a cancellable promise
|
|
87
|
+
const futurable = new Futurable((resolve, reject, { cancel, signal }) => {
|
|
88
|
+
const timeoutId = setTimeout(() => resolve('Done!'), 2000);
|
|
305
89
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
90
|
+
// Clean up when cancelled
|
|
91
|
+
signal.addEventListener('abort', () => {
|
|
92
|
+
clearTimeout(timeoutId);
|
|
93
|
+
});
|
|
309
94
|
});
|
|
310
95
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
futurable
|
|
314
|
-
.delay((val)=> {
|
|
315
|
-
console.log("delayed val", val);
|
|
316
|
-
return val;
|
|
317
|
-
},3000)
|
|
318
|
-
.then(val => .......);
|
|
319
|
-
|
|
320
|
-
//...code
|
|
96
|
+
// Cancel it before it completes
|
|
97
|
+
setTimeout(() => futurable.cancel(), 1000);
|
|
321
98
|
```
|
|
322
99
|
|
|
323
|
-
|
|
324
|
-
Fetch API extension with cancellation support. Url parameter can be a string or a function with receive value from futurable chaining as paremeter.
|
|
325
|
-
|
|
326
|
-
*Example*
|
|
327
|
-
```javascript
|
|
328
|
-
const futurable = new Futurable((resolve, reject, utils) => {
|
|
329
|
-
utils.fetch(/*string url to fetch..*/)
|
|
330
|
-
.then(val => resolve(val))
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
//...code
|
|
334
|
-
|
|
335
|
-
//OR
|
|
100
|
+
---
|
|
336
101
|
|
|
337
|
-
|
|
338
|
-
// asynchornous code..
|
|
339
|
-
resolve(true);
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
//...code
|
|
343
|
-
|
|
344
|
-
futurable
|
|
345
|
-
.fetch(/*url to fetch..*/)
|
|
346
|
-
.then(val => .......);
|
|
347
|
-
|
|
348
|
-
//OR
|
|
349
|
-
futurable
|
|
350
|
-
.then(val => "https://...")
|
|
351
|
-
.fetch((val /* val came from previous then*/) => ..., ..)
|
|
102
|
+
## 💡 Examples
|
|
352
103
|
|
|
353
|
-
|
|
354
|
-
```
|
|
104
|
+
### Cancellable Fetch Request
|
|
355
105
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
Transforms the futurable into a normal promise in order to be able to use the async/await syntax but keeping possibility to cancel futurable until its invocation.
|
|
106
|
+
```typescript
|
|
107
|
+
import { Futurable } from '@ndriadev/futurable';
|
|
359
108
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
109
|
+
// Make a cancellable API request
|
|
110
|
+
const request = Futurable.fetch('https://api.example.com/data')
|
|
111
|
+
.then(response => response.json())
|
|
112
|
+
.then(data => console.log(data))
|
|
113
|
+
.catch(error => console.error('Request failed:', error));
|
|
365
114
|
|
|
366
|
-
|
|
367
|
-
|
|
115
|
+
// Cancel after 5 seconds if not completed
|
|
116
|
+
setTimeout(() => request.cancel(), 5000);
|
|
368
117
|
```
|
|
369
|
-
--->
|
|
370
|
-
### futurizable(promise: Promise | (val => Promise))
|
|
371
|
-
Takes a promise and transforms it into a futurable. Promise can be also a function that receives value from futurable chaining as parameter.
|
|
372
|
-
|
|
373
|
-
*Example*
|
|
374
|
-
```javascript
|
|
375
|
-
const futurable = new Futurable((resolve, reject, utils) => {
|
|
376
|
-
utils.futurizable(new Promise(res => {
|
|
377
|
-
//asynchronous code
|
|
378
|
-
res(data);
|
|
379
|
-
}))
|
|
380
|
-
.then(val => resolve(val))
|
|
381
|
-
});
|
|
382
118
|
|
|
383
|
-
|
|
119
|
+
### React Hook with Auto-Cleanup
|
|
384
120
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
// asynchornous code..
|
|
389
|
-
resolve(true);
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
//...code
|
|
393
|
-
|
|
394
|
-
futurable
|
|
395
|
-
.futurizable(/*promise to futurizable*/)
|
|
396
|
-
.then(val => .......);
|
|
397
|
-
|
|
398
|
-
//OR
|
|
399
|
-
futurable
|
|
400
|
-
.then(val => 3)
|
|
401
|
-
.futurizable((val /* val is 3 */) => new Promise(/*...*/) /*promise to futurizable*/, ..)
|
|
121
|
+
```typescript
|
|
122
|
+
import { useEffect, useState } from 'react';
|
|
123
|
+
import { Futurable } from '@ndriadev/futurable';
|
|
402
124
|
|
|
403
|
-
|
|
404
|
-
|
|
125
|
+
function UserProfile({ userId }) {
|
|
126
|
+
const [user, setUser] = useState(null);
|
|
405
127
|
|
|
406
|
-
|
|
407
|
-
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
const request = Futurable
|
|
130
|
+
.fetch(`https://api.example.com/users/${userId}`)
|
|
131
|
+
.then(res => res.json())
|
|
132
|
+
.then(setUser);
|
|
408
133
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
134
|
+
// Automatically cancel on component unmount
|
|
135
|
+
return () => request.cancel();
|
|
136
|
+
}, [userId]);
|
|
412
137
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
cb: ()=>console.log("Cancelled"),
|
|
416
|
-
signal: controller.signal
|
|
417
|
-
});
|
|
418
|
-
//...code
|
|
138
|
+
return <div>{user?.name}</div>;
|
|
139
|
+
}
|
|
419
140
|
```
|
|
420
141
|
|
|
421
|
-
###
|
|
422
|
-
Sleep static method. It accepts a timer or a object with timer property and an optional signal.
|
|
423
|
-
|
|
424
|
-
*Example*
|
|
425
|
-
```javascript
|
|
426
|
-
//...code
|
|
427
|
-
|
|
428
|
-
Futurable.sleep({
|
|
429
|
-
timer: 3000,
|
|
430
|
-
signal: signal
|
|
431
|
-
});
|
|
432
|
-
|
|
433
|
-
//...code
|
|
434
|
-
```
|
|
142
|
+
### Sleep & Delay
|
|
435
143
|
|
|
436
|
-
|
|
437
|
-
|
|
144
|
+
```typescript
|
|
145
|
+
import { Futurable } from '@ndriadev/futurable';
|
|
438
146
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
//...code
|
|
147
|
+
// Simple sleep
|
|
148
|
+
await Futurable.sleep(1000); // Wait 1 second
|
|
149
|
+
console.log('Slept for 1 second');
|
|
443
150
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
});
|
|
151
|
+
// Delay with callback
|
|
152
|
+
const result = await new Futurable((resolve) => {
|
|
153
|
+
resolve('initial value');
|
|
154
|
+
}).delay(() => 'delayed value', 2000);
|
|
448
155
|
|
|
449
|
-
|
|
156
|
+
console.log(result); // 'delayed value' after 2 seconds
|
|
450
157
|
```
|
|
451
158
|
|
|
452
|
-
###
|
|
453
|
-
Fetch static method.
|
|
454
|
-
|
|
455
|
-
*Example*
|
|
456
|
-
```javascript
|
|
457
|
-
//...code
|
|
458
|
-
|
|
459
|
-
Futurable.fetch(/*url string..*/, {method: "POST"});
|
|
159
|
+
### Polling
|
|
460
160
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
### Futurable.futurizable({promise: Promise, signal: AbortSignal})
|
|
465
|
-
Futurizable static method.
|
|
161
|
+
```typescript
|
|
162
|
+
import { Futurable } from '@ndriadev/futurable';
|
|
466
163
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
164
|
+
// Poll an API endpoint every 5 seconds
|
|
165
|
+
const polling = Futurable.polling(
|
|
166
|
+
() => Futurable.fetch('https://api.example.com/status')
|
|
167
|
+
.then(res => res.json()),
|
|
168
|
+
5000 // interval in ms
|
|
169
|
+
);
|
|
471
170
|
|
|
472
|
-
|
|
171
|
+
polling
|
|
172
|
+
.then(data => console.log('Status:', data))
|
|
173
|
+
.catch(error => console.error('Polling error:', error));
|
|
473
174
|
|
|
474
|
-
|
|
175
|
+
// Stop polling after 30 seconds
|
|
176
|
+
setTimeout(() => polling.cancel(), 30000);
|
|
475
177
|
```
|
|
476
178
|
|
|
477
|
-
###
|
|
478
|
-
Extension of the static method _all_ with cancellation support.
|
|
479
|
-
|
|
480
|
-
*Example*
|
|
481
|
-
```javascript
|
|
482
|
-
const controller = new AbortController();
|
|
483
|
-
|
|
484
|
-
//...code
|
|
485
|
-
|
|
486
|
-
Futurable.all([
|
|
487
|
-
1,
|
|
488
|
-
Futurable.resolve(true, controlles.signal),
|
|
489
|
-
new Futurable/*...*/
|
|
490
|
-
], controller.signal);
|
|
491
|
-
|
|
492
|
-
//...code
|
|
493
|
-
|
|
494
|
-
controller.abort();
|
|
495
|
-
|
|
496
|
-
//OR
|
|
179
|
+
### Convert Existing Promises
|
|
497
180
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
Futurable.resolve(true),
|
|
501
|
-
new Futurable/*...*/
|
|
502
|
-
]
|
|
181
|
+
```typescript
|
|
182
|
+
import { Futurable } from '@ndriadev/futurable';
|
|
503
183
|
|
|
504
|
-
|
|
184
|
+
// Convert any promise to a Futurable
|
|
185
|
+
const regularPromise = fetch('https://api.example.com/data');
|
|
186
|
+
const futurable = Futurable.futurizable(regularPromise);
|
|
505
187
|
|
|
506
|
-
|
|
188
|
+
// Now it's cancellable!
|
|
189
|
+
futurable.cancel();
|
|
507
190
|
```
|
|
508
191
|
|
|
509
|
-
###
|
|
510
|
-
Extension of the static method _allSettled_ with cancellation support.
|
|
511
|
-
|
|
512
|
-
*Example*
|
|
513
|
-
```javascript
|
|
514
|
-
const controller = new AbortController();
|
|
515
|
-
|
|
516
|
-
//...code
|
|
517
|
-
|
|
518
|
-
Futurable.allSettled([
|
|
519
|
-
1,
|
|
520
|
-
Futurable.resolve(true, controller.signal),
|
|
521
|
-
new Futurable/*...*/
|
|
522
|
-
], controller.signal);
|
|
523
|
-
|
|
524
|
-
//...code
|
|
525
|
-
|
|
526
|
-
controller.abort();
|
|
192
|
+
### Static Methods (All Promise Methods Supported)
|
|
527
193
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
const f = Futurable.allSettled([
|
|
531
|
-
1,
|
|
532
|
-
Futurable.resolve(true),
|
|
533
|
-
new Futurable/*...*/
|
|
534
|
-
];
|
|
194
|
+
```typescript
|
|
195
|
+
import { Futurable } from '@ndriadev/futurable';
|
|
535
196
|
|
|
536
|
-
|
|
197
|
+
// All static Promise methods work with cancellation support
|
|
198
|
+
const results = await Futurable.all([
|
|
199
|
+
Futurable.fetch('/api/users'),
|
|
200
|
+
Futurable.fetch('/api/posts'),
|
|
201
|
+
Futurable.fetch('/api/comments')
|
|
202
|
+
]);
|
|
537
203
|
|
|
538
|
-
|
|
204
|
+
// Cancel all requests at once
|
|
205
|
+
results.cancel();
|
|
539
206
|
```
|
|
540
207
|
|
|
541
|
-
|
|
542
|
-
Extension of the static method _any_ with cancellation support.
|
|
543
|
-
|
|
544
|
-
*Example*
|
|
545
|
-
```javascript
|
|
546
|
-
const controller = new AbortController();
|
|
547
|
-
//...code
|
|
548
|
-
|
|
549
|
-
Futurable.any([
|
|
550
|
-
1,
|
|
551
|
-
Futurable.resolve(true, controller.signal),
|
|
552
|
-
new Futurable/*...*/
|
|
553
|
-
], controller.signal);
|
|
554
|
-
|
|
555
|
-
//...code
|
|
556
|
-
|
|
557
|
-
controller.abort();
|
|
558
|
-
|
|
559
|
-
//OR
|
|
208
|
+
---
|
|
560
209
|
|
|
561
|
-
|
|
562
|
-
1,
|
|
563
|
-
Futurable.resolve(true, controller.signal),
|
|
564
|
-
new Futurable/*...*/
|
|
565
|
-
];
|
|
210
|
+
## 📚 API Reference
|
|
566
211
|
|
|
567
|
-
|
|
212
|
+
For complete API documentation, visit [futurable.ndria.dev](https://futurable.ndria.dev/)
|
|
568
213
|
|
|
569
|
-
|
|
570
|
-
```
|
|
214
|
+
### Core Methods
|
|
571
215
|
|
|
572
|
-
|
|
573
|
-
|
|
216
|
+
| Method | Description |
|
|
217
|
+
|--------|-------------|
|
|
218
|
+
| `cancel()` | Cancels the futurable operation |
|
|
219
|
+
| `onCancel(callback)` | Executes callback when cancelled |
|
|
220
|
+
| `sleep(ms)` | Waits for specified milliseconds |
|
|
221
|
+
| `delay(callback, ms)` | Delays execution of callback |
|
|
222
|
+
| `fetch(url, options)` | Cancellable fetch request |
|
|
223
|
+
| `futurizable(promise)` | Converts Promise to Futurable |
|
|
574
224
|
|
|
575
|
-
|
|
576
|
-
```javascript
|
|
577
|
-
const controller = new AbortController();
|
|
578
|
-
//...code
|
|
225
|
+
### Static Methods
|
|
579
226
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
227
|
+
All native Promise static methods are supported:
|
|
228
|
+
- `Futurable.all()`
|
|
229
|
+
- `Futurable.allSettled()`
|
|
230
|
+
- `Futurable.any()`
|
|
231
|
+
- `Futurable.race()`
|
|
232
|
+
- `Futurable.resolve()`
|
|
233
|
+
- `Futurable.reject()`
|
|
234
|
+
- `Futurable.withResolvers()`
|
|
585
235
|
|
|
586
|
-
|
|
236
|
+
Plus additional methods:
|
|
237
|
+
- `Futurable.polling()` - Polling with interval support
|
|
238
|
+
- `Futurable.sleep()` - Static sleep utility
|
|
239
|
+
- `Futurable.delay()` - Static delay utility
|
|
240
|
+
- `Futurable.fetch()` - Static fetch utility
|
|
241
|
+
- `Futurable.futurizable()` - Convert Promise to Futurable
|
|
587
242
|
|
|
588
|
-
|
|
243
|
+
---
|
|
589
244
|
|
|
590
|
-
|
|
245
|
+
## 🎯 Use Cases
|
|
591
246
|
|
|
592
|
-
|
|
593
|
-
1,
|
|
594
|
-
Futurable.resolve(true, controller.signal),
|
|
595
|
-
new Futurable/*...*/
|
|
596
|
-
];
|
|
247
|
+
### Perfect For
|
|
597
248
|
|
|
598
|
-
|
|
249
|
+
- **SPA Applications** - Cancel API calls when navigating away
|
|
250
|
+
- **React/Vue/Angular** - Clean up effects and prevent memory leaks
|
|
251
|
+
- **Real-time Updates** - Implement polling with easy cancellation
|
|
252
|
+
- **Long-running Operations** - Timeout or cancel expensive operations
|
|
253
|
+
- **Resource Management** - Proper cleanup of async resources
|
|
254
|
+
- **Testing** - Better control over async test scenarios
|
|
599
255
|
|
|
600
|
-
|
|
601
|
-
```
|
|
256
|
+
---
|
|
602
257
|
|
|
603
|
-
|
|
604
|
-
Creates a polling service with cancellation support and possibility to handle error. An optional param __immediate__ can be set _true_ if __fun__ must to be invoke immediatly.
|
|
258
|
+
## 🌐 Browser & Node.js Support
|
|
605
259
|
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
const polling = Futurable.polling(() => Futurable.fetch(/*...*/)), {interval: 1000});
|
|
610
|
-
polling.catch(err => console.error(err));
|
|
260
|
+
- ✅ All modern browsers (Chrome, Firefox, Safari, Edge)
|
|
261
|
+
- ✅ Node.js 14+ (Native Fetch API support in Node.js 17.5+)
|
|
262
|
+
- ✅ TypeScript 4.5+
|
|
611
263
|
|
|
612
|
-
|
|
264
|
+
> **Note for Node.js < 17.5:** Install `node-fetch` for fetch functionality
|
|
613
265
|
|
|
614
|
-
|
|
615
|
-
```
|
|
266
|
+
---
|
|
616
267
|
|
|
617
|
-
|
|
618
|
-
Extension of static method _withResolvers_ with support of _cancel_ function and _utils_ object of Futurable.
|
|
268
|
+
## 📄 License
|
|
619
269
|
|
|
620
|
-
|
|
621
|
-
```javascript
|
|
622
|
-
//...code
|
|
623
|
-
const {promise, resolve, reject} = Futurable.withResolvers();
|
|
270
|
+
[MIT](LICENSE) © [nDriaDev](https://github.com/nDriaDev)
|
|
624
271
|
|
|
625
|
-
|
|
272
|
+
---
|
|
626
273
|
|
|
627
|
-
|
|
274
|
+
## 📞 Support
|
|
628
275
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
276
|
+
- **Issues:** [GitHub Issues](https://github.com/nDriaDev/vite-plugin-universal-api/issues)
|
|
277
|
+
- **Discussions:** [GitHub Discussions](https://github.com/nDriaDev/vite-plugin-universal-api/discussions)
|
|
278
|
+
- **Email:** info@ndria.dev
|
|
632
279
|
|
|
280
|
+
---
|
|
633
281
|
|
|
634
|
-
# ToDo
|
|
635
|
-
- Extends fetch api support to third library like axios.
|
|
636
|
-
- Implement promise cache.
|
|
637
282
|
|
|
638
283
|
|
|
639
|
-
|
|
640
|
-
|
|
284
|
+
<div align="center">
|
|
641
285
|
|
|
642
286
|
|
|
643
|
-
|
|
287
|
+
If you find this plugin useful, please consider giving it a ⭐ on [GitHub](https://github.com/nDriaDev/vite-plugin-universal-api)!
|
|
288
|
+
</div>
|