101 lines
2.5 KiB
JavaScript
101 lines
2.5 KiB
JavaScript
/**
|
|
* An event hub with a Vue instance like API
|
|
*
|
|
* NOTE: There's an [issue open][4] to eventually remove this when some
|
|
* coupling in our codebase has been fixed.
|
|
*
|
|
* NOTE: This is a derivative work from [mitt][1] v1.2.0 which is licensed by
|
|
* [MIT License][2] © [Jason Miller][3]
|
|
*
|
|
* [1]: https://github.com/developit/mitt
|
|
* [2]: https://opensource.org/licenses/MIT
|
|
* [3]: https://jasonformat.com/
|
|
* [4]: https://gitlab.com/gitlab-org/gitlab/-/issues/223864
|
|
*/
|
|
class EventHub {
|
|
constructor() {
|
|
this.$_all = new Map();
|
|
}
|
|
|
|
dispose() {
|
|
this.$_all.clear();
|
|
}
|
|
|
|
/**
|
|
* Register an event handler for the given type.
|
|
*
|
|
* @param {string|symbol} type Type of event to listen for
|
|
* @param {Function} handler Function to call in response to given event
|
|
*/
|
|
$on(type, handler) {
|
|
const handlers = this.$_all.get(type);
|
|
const added = handlers && handlers.push(handler);
|
|
|
|
if (!added) {
|
|
this.$_all.set(type, [handler]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove an event handler or all handlers for the given type.
|
|
*
|
|
* @param {string|symbol} type Type of event to unregister `handler`
|
|
* @param {Function} handler Handler function to remove
|
|
*/
|
|
$off(type, handler) {
|
|
const handlers = this.$_all.get(type) || [];
|
|
|
|
const newHandlers = handler ? handlers.filter((x) => x !== handler) : [];
|
|
|
|
if (newHandlers.length) {
|
|
this.$_all.set(type, newHandlers);
|
|
} else {
|
|
this.$_all.delete(type);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add an event listener to type but only trigger it once
|
|
*
|
|
* @param {string|symbol} type Type of event to listen for
|
|
* @param {Function} handler Handler function to call in response to event
|
|
*/
|
|
$once(type, handler) {
|
|
const wrapHandler = (...args) => {
|
|
this.$off(type, wrapHandler);
|
|
handler(...args);
|
|
};
|
|
this.$on(type, wrapHandler);
|
|
}
|
|
|
|
/**
|
|
* Invoke all handlers for the given type.
|
|
*
|
|
* @param {string|symbol} type The event type to invoke
|
|
* @param {Any} [evt] Any value passed to each handler
|
|
*/
|
|
$emit(type, ...args) {
|
|
const handlers = this.$_all.get(type) || [];
|
|
|
|
handlers.forEach((handler) => {
|
|
handler(...args);
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return a Vue like event hub
|
|
*
|
|
* - $on
|
|
* - $off
|
|
* - $once
|
|
* - $emit
|
|
*
|
|
* Please note, this was once implemented with `mitt`, but since then has been reverted
|
|
* because of some API issues. https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35074
|
|
*
|
|
* We'd like to shy away from using a full fledged Vue instance from this in the future.
|
|
*/
|
|
export default () => {
|
|
return new EventHub();
|
|
};
|