@hardlydifficult/poller 1.0.2 → 1.0.3
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 +129 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @hardlydifficult/poller
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Polls an async function at a configurable interval and triggers callbacks when the result changes.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ Generic state-change poller. Polls a function at an interval and fires a callbac
|
|
|
8
8
|
npm install @hardlydifficult/poller
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Quick Start
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
14
|
import { Poller } from "@hardlydifficult/poller";
|
|
@@ -28,9 +28,127 @@ poller.trigger(1000);
|
|
|
28
28
|
poller.stop();
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
##
|
|
31
|
+
## Polling
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
The `Poller` class periodically fetches data and invokes a callback when the result changes. It fetches immediately on `start()`, then at the configured interval.
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { Poller } from "@hardlydifficult/poller";
|
|
37
|
+
|
|
38
|
+
const poller = new Poller(
|
|
39
|
+
async () => {
|
|
40
|
+
const response = await fetch("/api/status");
|
|
41
|
+
return response.json();
|
|
42
|
+
},
|
|
43
|
+
(current, previous) => {
|
|
44
|
+
console.log("Previous:", previous);
|
|
45
|
+
console.log("Current:", current);
|
|
46
|
+
},
|
|
47
|
+
10000 // poll every 10 seconds
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
await poller.start();
|
|
51
|
+
// Fetches immediately, then every 10 seconds
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Change Detection
|
|
55
|
+
|
|
56
|
+
Changes are detected using JSON serialization for deep equality. Structurally identical objects are considered unchanged, even if they are different references.
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
const poller = new Poller(
|
|
60
|
+
async () => ({ count: 5, items: [1, 2, 3] }),
|
|
61
|
+
(current, previous) => {
|
|
62
|
+
// Only fires when the JSON representation changes
|
|
63
|
+
console.log("Changed from", previous, "to", current);
|
|
64
|
+
},
|
|
65
|
+
5000
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
await poller.start();
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Manual Triggers
|
|
72
|
+
|
|
73
|
+
Call `trigger()` to manually poll immediately, with optional debouncing. Multiple rapid triggers are coalesced into a single poll.
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
const poller = new Poller(
|
|
77
|
+
async () => await fetchData(),
|
|
78
|
+
(current, previous) => console.log("Updated:", current),
|
|
79
|
+
60000
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
await poller.start();
|
|
83
|
+
|
|
84
|
+
// Trigger a poll with 1000ms debounce (default)
|
|
85
|
+
poller.trigger();
|
|
86
|
+
|
|
87
|
+
// Trigger with custom debounce
|
|
88
|
+
poller.trigger(500);
|
|
89
|
+
|
|
90
|
+
// Multiple rapid triggers coalesce into one poll
|
|
91
|
+
poller.trigger(500);
|
|
92
|
+
poller.trigger(500);
|
|
93
|
+
poller.trigger(500); // Only one poll fires after 500ms
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Error Handling
|
|
97
|
+
|
|
98
|
+
Errors during fetch are passed to the optional `onError` callback. Polling continues regardless of errors.
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
const poller = new Poller(
|
|
102
|
+
async () => await fetchData(),
|
|
103
|
+
(current, previous) => console.log("Updated:", current),
|
|
104
|
+
5000,
|
|
105
|
+
(error) => {
|
|
106
|
+
console.error("Fetch failed:", error);
|
|
107
|
+
// Polling continues automatically
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
await poller.start();
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Lifecycle
|
|
115
|
+
|
|
116
|
+
### `start()`
|
|
117
|
+
|
|
118
|
+
Starts polling. Fetches immediately, then at the configured interval. Calling `start()` multiple times is safe (idempotent).
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
const poller = new Poller(
|
|
122
|
+
async () => await fetchData(),
|
|
123
|
+
(current) => console.log("Updated:", current),
|
|
124
|
+
5000
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
await poller.start(); // Fetches immediately
|
|
128
|
+
await poller.start(); // No-op, already running
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### `stop()`
|
|
132
|
+
|
|
133
|
+
Stops polling and cleans up all timers.
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
poller.stop();
|
|
137
|
+
// No more polls will fire
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## API Reference
|
|
141
|
+
|
|
142
|
+
### Constructor
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
new Poller<T>(
|
|
146
|
+
fetchFn: () => Promise<T>,
|
|
147
|
+
onChange: (current: T, previous: T | undefined) => void,
|
|
148
|
+
intervalMs: number,
|
|
149
|
+
onError?: (error: unknown) => void
|
|
150
|
+
)
|
|
151
|
+
```
|
|
34
152
|
|
|
35
153
|
| Parameter | Description |
|
|
36
154
|
|-----------|-------------|
|
|
@@ -39,6 +157,8 @@ poller.stop();
|
|
|
39
157
|
| `intervalMs` | Polling interval in milliseconds |
|
|
40
158
|
| `onError` | Optional error handler; polling continues on errors |
|
|
41
159
|
|
|
160
|
+
### Methods
|
|
161
|
+
|
|
42
162
|
| Method | Description |
|
|
43
163
|
|--------|-------------|
|
|
44
164
|
| `start()` | Start polling (fetches immediately, then at interval) |
|
|
@@ -47,7 +167,8 @@ poller.stop();
|
|
|
47
167
|
|
|
48
168
|
### Behavior
|
|
49
169
|
|
|
50
|
-
- **Deep equality**
|
|
51
|
-
- **Overlap prevention**
|
|
52
|
-
- **Error resilience**
|
|
53
|
-
- **Idempotent start**
|
|
170
|
+
- **Deep equality** — uses JSON serialization to detect changes
|
|
171
|
+
- **Overlap prevention** — skips a poll if the previous fetch is still running
|
|
172
|
+
- **Error resilience** — continues polling after fetch errors
|
|
173
|
+
- **Idempotent start** — calling `start()` multiple times is safe
|
|
174
|
+
- **Debounced triggers** — multiple `trigger()` calls coalesce into one poll
|