Skip to content

Commit

Permalink
feat(useEventBus): new Function once (vitest-dev#680)
Browse files Browse the repository at this point in the history
Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
  • Loading branch information
hairyf and antfu committed Sep 2, 2021
1 parent 3b2d884 commit a39ec87
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 5 deletions.
11 changes: 11 additions & 0 deletions packages/core/useEventBus/index.test.ts
Expand Up @@ -24,6 +24,17 @@ describe('useEventBus', () => {
reset()
expect(events).toEqual(emptyMap)
})
it('once event', () => {
const { once, emit, reset } = useEventBus<number>('foo')
const { inc, count } = useCounter(0)
once(inc)
emit()
emit()
emit()
expect(count.value).toBe(1)
reset()
expect(events).toEqual(emptyMap)
})
it('on callback off event', () => {
const bus = useEventBus<number>('on-callback-off')
const { count, inc } = useCounter(0)
Expand Down
21 changes: 18 additions & 3 deletions packages/core/useEventBus/index.ts
Expand Up @@ -6,7 +6,7 @@ export type EventBusListener<T = unknown> = (event: T) => void
export type EventBusEvents<T> = EventBusListener<T>[]

export interface EventBusKey<T> extends Symbol { }
export type EventBusIdentifer<T = unknown> = EventBusKey<T> | string | number
export type EventBusIdentifier<T = unknown> = EventBusKey<T> | string | number

export interface UseEventBusReturn<T> {
/**
Expand All @@ -15,6 +15,12 @@ export interface UseEventBusReturn<T> {
* @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.
Expand All @@ -31,7 +37,7 @@ export interface UseEventBusReturn<T> {
reset: () => void
}

export function useEventBus<T = unknown>(key: EventBusIdentifer<T>): UseEventBusReturn<T> {
export function useEventBus<T = unknown>(key: EventBusIdentifier<T>): UseEventBusReturn<T> {
const scope = getCurrentScope()

function on(listener: EventBusListener<T>) {
Expand All @@ -45,6 +51,15 @@ export function useEventBus<T = unknown>(key: EventBusIdentifer<T>): UseEventBus
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)
Expand All @@ -65,5 +80,5 @@ export function useEventBus<T = unknown>(key: EventBusIdentifer<T>): UseEventBus
events.get(key)?.forEach(v => v(event))
}

return { on, off, emit, reset }
return { on, once, off, emit, reset }
}
4 changes: 2 additions & 2 deletions packages/core/useEventBus/internal.ts
@@ -1,4 +1,4 @@
import { EventBusEvents, EventBusIdentifer } from '.'
import { EventBusEvents, EventBusIdentifier } from '.'

/* #__PURE__ */
export const events = new Map<EventBusIdentifer<any>, EventBusEvents<any>>()
export const events = new Map<EventBusIdentifier<any>, EventBusEvents<any>>()

0 comments on commit a39ec87

Please sign in to comment.