Run one-shot and parallel hooks
Run a handler at most once
A hookOnce registration makes its handler eligible to run at most once. Dispatching the same hook again does not invoke that registration again.
import { createHooks } from "hookable";
interface RunOnceHookMap {
"test-hook": () => void;
}
async function runOnceExample() {
const hooks = createHooks<RunOnceHookMap>();
let counter = 0;
hooks.hookOnce("test-hook", () => {
counter++;
});
await hooks.callHook("test-hook");
await hooks.callHook("test-hook");
console.assert(counter === 1);
}
await runOnceExample();
Dispatch asynchronous handlers and remove one
Register two named asynchronous handlers before calling callHookParallel. A synchronous callback throw can prevent later callbacks from starting. A callback-returned rejecting Promise rejects the returned Promise.
import { createHooks } from "hookable";
interface ParallelHookMap {
"app:start": () => void | Promise<void>;
}
async function parallelExecutionExample() {
const hooks = createHooks<ParallelHookMap>();
const trace: string[] = [];
const initAnalytics = async () => {
trace.push("start:analytics");
await new Promise(resolve => setTimeout(resolve, 50));
trace.push("end:analytics");
};
const connectDatabase = async () => {
trace.push("start:db");
await new Promise(resolve => setTimeout(resolve, 100));
trace.push("end:db");
};
hooks.hook("app:start", initAnalytics);
hooks.hook("app:start", connectDatabase);
await hooks.callHookParallel("app:start");
console.log(JSON.stringify(trace));
hooks.removeHook("app:start", initAnalytics);
trace.length = 0;
await hooks.callHookParallel("app:start");
console.log(JSON.stringify(trace));
}
await parallelExecutionExample();
Pass the original function reference to removeHook, clear the trace, and dispatch again to observe the remaining registration.