Skip to content

Commit 7c18938

Browse files
committed
docs: add a small usage example for each hook class
Each hook class subsection now includes a short snippet illustrating typical taps and the corresponding call/result, following up on #48.
1 parent 8ddce2b commit 7c18938

1 file changed

Lines changed: 94 additions & 0 deletions

File tree

README.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,69 +196,163 @@ A basic synchronous hook. Every tapped function is called in registration order
196196
- Call methods: `call`
197197
- `tapAsync` and `tapPromise` throw an error.
198198

199+
```js
200+
const hook = new SyncHook(["name"]);
201+
hook.tap("A", (name) => console.log(`hello ${name}`));
202+
hook.tap("B", (name) => console.log(`hi ${name}`));
203+
hook.call("world");
204+
// hello world
205+
// hi world
206+
```
207+
199208
### SyncBailHook
200209

201210
A synchronous hook that allows exiting early. Every tapped function is called in order until one returns a non-`undefined` value; that value becomes the result of `call` and the remaining taps are skipped. If all taps return `undefined`, `call` returns `undefined`.
202211

203212
- Tap methods: `tap`
204213
- Call methods: `call`
205214

215+
```js
216+
const hook = new SyncBailHook(["value"]);
217+
hook.tap("Negative", (v) => (v < 0 ? "negative" : undefined));
218+
hook.tap("Zero", (v) => (v === 0 ? "zero" : undefined));
219+
hook.tap("Positive", (v) => "positive");
220+
221+
hook.call(-1); // "negative" (later taps skipped)
222+
hook.call(5); // "positive"
223+
```
224+
206225
### SyncWaterfallHook
207226

208227
A synchronous hook that threads a value through its tapped functions. The first argument passed to `call` is forwarded to the first tap. If a tap returns a non-`undefined` value it replaces that argument for the next tap; otherwise the previous value is kept. `call` returns the value after the last tap has run. Additional arguments (if any) are passed through unchanged.
209228

210229
- Tap methods: `tap`
211230
- Call methods: `call`
212231

232+
```js
233+
const hook = new SyncWaterfallHook(["value"]);
234+
hook.tap("Double", (v) => v * 2);
235+
hook.tap("PlusOne", (v) => v + 1);
236+
237+
hook.call(3); // 7 -> (3 * 2) + 1
238+
```
239+
213240
### SyncLoopHook
214241

215242
A synchronous hook that keeps re-running its taps until all of them return `undefined` for a full pass. Whenever a tap returns a non-`undefined` value the hook restarts from the first tap. `call` returns `undefined`.
216243

217244
- Tap methods: `tap`
218245
- Call methods: `call`
219246

247+
```js
248+
const hook = new SyncLoopHook(["state"]);
249+
let retries = 3;
250+
hook.tap("Retry", () => {
251+
if (retries-- > 0) return true; // non-undefined restarts the loop
252+
});
253+
hook.tap("Log", () => console.log("pass"));
254+
255+
hook.call({});
256+
// pass (runs once all taps return undefined)
257+
```
258+
220259
### AsyncParallelHook
221260

222261
An asynchronous hook that runs all of its tapped functions in parallel. It completes when every tap has signalled completion (sync return, callback, or promise resolution). Return values and resolution values are ignored; `callAsync`'s callback is invoked with no result and `promise()` resolves to `undefined`. If any tap errors, the error is forwarded and remaining taps still complete but their results are discarded.
223262

224263
- Tap methods: `tap`, `tapAsync`, `tapPromise`
225264
- Call methods: `callAsync`, `promise`
226265

266+
```js
267+
const hook = new AsyncParallelHook(["source"]);
268+
hook.tapPromise("Fetch", (src) => fetch(src));
269+
hook.tapAsync("Log", (src, cb) => {
270+
console.log("fetching", src);
271+
cb();
272+
});
273+
274+
await hook.promise("https://example.com");
275+
```
276+
227277
### AsyncParallelBailHook
228278

229279
Like `AsyncParallelHook`, but designed to bail out with a result. All tapped functions start in parallel; the first tap to produce a non-`undefined` value (synchronously, via its callback, or by resolving its promise) determines the hook’s result. The remaining taps continue to run but their results are ignored. Order is determined by tap registration order: an earlier tap’s value takes precedence over a later one’s, even if the later one finishes first.
230280

231281
- Tap methods: `tap`, `tapAsync`, `tapPromise`
232282
- Call methods: `callAsync`, `promise`
233283

284+
```js
285+
const hook = new AsyncParallelBailHook(["key"]);
286+
hook.tapPromise("Cache", async (key) => cache.get(key));
287+
hook.tapPromise("Db", async (key) => db.lookup(key));
288+
289+
const value = await hook.promise("user:42");
290+
// First non-undefined result (by registration order) wins.
291+
```
292+
234293
### AsyncSeriesHook
235294

236295
An asynchronous hook that runs tapped functions one after another, waiting for each to finish before starting the next. Results are ignored; `callAsync`'s callback is invoked with no result and `promise()` resolves to `undefined`. The first error aborts the series.
237296

238297
- Tap methods: `tap`, `tapAsync`, `tapPromise`
239298
- Call methods: `callAsync`, `promise`
240299

300+
```js
301+
const hook = new AsyncSeriesHook(["request"]);
302+
hook.tapPromise("Authenticate", async (req) => authenticate(req));
303+
hook.tapPromise("Log", async (req) => logger.info(req.url));
304+
305+
await hook.promise(request);
306+
```
307+
241308
### AsyncSeriesBailHook
242309

243310
An asynchronous series hook that allows exiting early. Tapped functions run one after another; as soon as one produces a non-`undefined` value, that value becomes the hook’s result and the remaining taps are skipped.
244311

245312
- Tap methods: `tap`, `tapAsync`, `tapPromise`
246313
- Call methods: `callAsync`, `promise`
247314

315+
```js
316+
const hook = new AsyncSeriesBailHook(["id"]);
317+
hook.tapPromise("Memory", async (id) => memory.get(id));
318+
hook.tapPromise("Disk", async (id) => disk.read(id));
319+
320+
const value = await hook.promise("doc-1");
321+
// Stops at the first tap that produces a value.
322+
```
323+
248324
### AsyncSeriesLoopHook
249325

250326
An asynchronous series hook that loops. Tapped functions run one after another; whenever a tap produces a non-`undefined` value the hook restarts from the first tap. The hook completes once a full pass yields `undefined` from every tap. The result is always `undefined`.
251327

252328
- Tap methods: `tap`, `tapAsync`, `tapPromise`
253329
- Call methods: `callAsync`, `promise`
254330

331+
```js
332+
const hook = new AsyncSeriesLoopHook(["job"]);
333+
hook.tapPromise("Process", async (job) => {
334+
const more = await job.step();
335+
if (more) return true; // restart the loop
336+
});
337+
338+
await hook.promise(job);
339+
```
340+
255341
### AsyncSeriesWaterfallHook
256342

257343
An asynchronous series hook that threads a value through its taps. The first argument passed to `callAsync` / `promise` is forwarded to the first tap. A tap's non-`undefined` return / callback / resolution value replaces it for the next tap; `undefined` keeps the previous value. The hook completes with the value after the last tap.
258344

259345
- Tap methods: `tap`, `tapAsync`, `tapPromise`
260346
- Call methods: `callAsync`, `promise`
261347

348+
```js
349+
const hook = new AsyncSeriesWaterfallHook(["source"]);
350+
hook.tapPromise("Read", async (src) => fs.readFile(src, "utf8"));
351+
hook.tapPromise("Trim", async (text) => text.trim());
352+
353+
const output = await hook.promise("./input.txt");
354+
```
355+
262356
## Interception
263357

264358
All Hooks offer an additional interception API:

0 commit comments

Comments
 (0)