Register and call typed hooks
Registering and calling hooks in hookable allows for structured, asynchronous event handling with full type guidance. By defining a hook contract, you ensure that handlers receive the correct arguments and that hook names are valid at development time.
Defining and Triggering Hooks
To manage hooks, create a typed instance using createHooks. You can then register multiple handlers for the same hook name. When you invoke callHook, hookable executes these handlers sequentially in the order they were registered. If a handler returns a promise, hookable awaits it before moving to the next handler.
import { createHooks } from "hookable";
interface MyHooks {
"start": () => void | Promise<void>;
}
async function runExample() {
const hooks = createHooks<MyHooks>();
const trace: string[] = [];
const handlerOne = () => {
trace.push("handler1");
};
const handlerTwo = () => {
trace.push("handler2");
};
hooks.hook("start", handlerOne);
hooks.hook("start", handlerTwo);
await hooks.callHook("start");
console.assert(trace[0] === "handler1");
console.assert(trace[1] === "handler2");
}
await runExample();
When calling hooks, if any handler throws an error or returns a promise that rejects, the callHook promise will reject with that error. In the successful path, all registered handlers are executed to completion.
Unregistering Handlers
The hook method returns a function that, when invoked, removes the specific handler from the execution sequence. This is useful for temporary listeners or cleanup logic in component-based architectures.
import { createHooks } from "hookable";
interface AppHooks {
"app:shutdown": () => void | Promise<void>;
}
async function runUnregisterExample() {
const hooks = createHooks<AppHooks>();
const trace: string[] = [];
const temporaryHandler = () => {
trace.push("temporary handler was called");
};
const unregister = hooks.hook("app:shutdown", temporaryHandler);
await hooks.callHook("app:shutdown");
console.assert(trace.length === 1);
unregister();
await hooks.callHook("app:shutdown");
console.assert(trace.length === 1);
}
await runUnregisterExample();