@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.
Files changed (2) hide show
  1. package/README.md +129 -8
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @hardlydifficult/poller
2
2
 
3
- Generic state-change poller. Polls a function at an interval and fires a callback when the result changes.
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
- ## Usage
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
- ## API
31
+ ## Polling
32
32
 
33
- ### `new Poller<T>(fetchFn, onChange, intervalMs, onError?)`
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** -- uses JSON serialization to detect changes
51
- - **Overlap prevention** -- skips a poll if the previous fetch is still running
52
- - **Error resilience** -- continues polling after fetch errors
53
- - **Idempotent start** -- calling `start()` multiple times is safe
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardlydifficult/poller",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [