afterEveryCommand(handler) registers a notification handler that runs after the handlers for every dispatched command. It returns a function that removes the registration. section 5.1.3
The method gives a dispatcher three focused responsibilities:
- Store handlers in a dedicated after-command collection rather than associating them with one command name. section 5.1.3
- Allow the same handler to be registered more than once because these handlers provide notifications rather than state updates. section 5.1.3
- Return an unsubscription function that removes the handler from the collection. section 5.1.3
- Invoke every registered after-command handler after command-specific handlers have run, including when no command-specific handler exists. section 5.1.3
Minimal implementation
class Dispatcher {\n #afterHandlers = []\n\n afterEveryCommand(handler) {\n this.#afterHandlers.push(handler)\n\n return () => {\n const index = this.#afterHandlers.indexOf(handler)\n this.#afterHandlers.splice(index, 1)\n }\n }\n\n dispatch(commandName, payload) {\n // Run handlers for commandName first.\n this.#afterHandlers.forEach((handler) => handler())\n }\n} section 5.1.3
Listing 5.2 Registering functions to run after commands (dispatcher.js)
export class Dispatcher {
#subs = new Map()
#afterHandlers = []
// --snip-- //
afterEveryCommand(handler) {
this.#afterHandlers.push(handler) #1
return () => { #2
const idx = this.#afterHandlers.indexOf(handler)
this.#afterHandlers.splice(idx, 1)
}
}
}
Inspect the complete registration and unsubscription implementation for after-command handlers. section 5.1.3
A state manager can register rendering as an after-command handler, then save the returned unsubscription function for application unmounting. Rendering after every command keeps the implementation simple because state changes cannot be known in advance; later DOM patching makes repeated rendering reasonably fast. section 5.2.3
