forked from vitest-dev/vitest
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
84 lines (72 loc) · 2.18 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import { Fn } from '@vueuse/shared'
import { getCurrentScope } from 'vue-demi'
import { events } from './internal'
export type EventBusListener<T = unknown> = (event: T) => void
export type EventBusEvents<T> = EventBusListener<T>[]
export interface EventBusKey<T> extends Symbol { }
export type EventBusIdentifier<T = unknown> = EventBusKey<T> | string | number
export interface UseEventBusReturn<T> {
/**
* Subscribe to an event. When calling emit, the listeners will execute.
* @param listener watch listener.
* @returns a stop function to remove the current callback.
*/
on: (listener: EventBusListener<T>) => Fn
/**
* Similar to `on`, but only fires once
* @param listener watch listener.
* @returns a stop function to remove the current callback.
*/
once: (listener: EventBusListener<T>) => Fn
/**
* Emit an event, the corresponding event listeners will execute.
* @param event data sent.
*/
emit: (event?: T) => void
/**
* Remove the corresponding listener.
* @param listener watch listener.
*/
off: (listener: EventBusListener<T>) => void
/**
* Clear all events
*/
reset: () => void
}
export function useEventBus<T = unknown>(key: EventBusIdentifier<T>): UseEventBusReturn<T> {
const scope = getCurrentScope()
function on(listener: EventBusListener<T>) {
const listeners = events.get(key) || []
listeners.push(listener)
events.set(key, listeners)
const _off = () => off(listener)
// auto unsubscribe when scope get disposed
scope?.cleanups.push(_off)
return _off
}
function once(listener: EventBusListener<T>) {
function _listener(...args: any[]) {
off(_listener)
// @ts-expect-error
listener(...args)
}
return on(_listener)
}
function off(listener: EventBusListener<T>): void {
const listeners = events.get(key)
if (!listeners)
return
const index = listeners.indexOf(listener)
if (index > -1)
listeners.splice(index, 1)
if (!listeners.length)
events.delete(key)
}
function reset() {
events.delete(key)
}
function emit(event?: T) {
events.get(key)?.forEach(v => v(event))
}
return { on, once, off, emit, reset }
}