Skip to content

Commit

Permalink
feat(EventBus): add off method
Browse files Browse the repository at this point in the history
  • Loading branch information
fjc0k committed Nov 14, 2018
1 parent bfdbf9f commit 1c43d87
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 24 deletions.
37 changes: 24 additions & 13 deletions src/EventBus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,15 @@ export default class EventBus<
* @param listener 监听器
* @returns 取消订阅函数
*/
public subscribe<X extends K>(eventName: X, listener: T[X]): EventBusUnsubscribe {
public on<X extends K>(eventName: X, listener: T[X]): EventBusUnsubscribe {
if (!this.listeners[eventName]) {
this.listeners[eventName] = []
}
const listeners = this.listeners[eventName]
if (listeners.indexOf(listener) === -1) {
listeners.push(listener)
}
return () => {
if (listener) {
const index = listeners.indexOf(listener)
if (index > -1) {
listeners.splice(index, 1)
listener = null
}
}
}
return () => this.off(eventName, listener)
}

/**
Expand All @@ -52,22 +44,41 @@ export default class EventBus<
* @param listener 监听器
* @returns 取消订阅函数
*/
public subscribeOnce<X extends K>(eventName: X, listener: T[X]): EventBusUnsubscribe {
const unsubscribe = this.subscribe(eventName, (...args: any[]) => {
public once<X extends K>(eventName: X, listener: T[X]): EventBusUnsubscribe {
const unsubscribe = this.on(eventName, (...args: any[]) => {
unsubscribe()
listener(...args)
})
return unsubscribe
}

/**
* 取消订阅事件,若没有指定监听器,则取消所有监听器。
*
* @param eventName 事件名称
* @param [listener] 监听器
*/
public off<X extends K>(eventName: X, listener?: T[X]): void {
if (listener) {
const listeners = this.listeners[eventName]
const index = listeners.indexOf(listener)
/* istanbul ignore else */
if (index > -1) {
listeners.splice(index, 1)
}
} else {
delete this.listeners[eventName]
}
}

/**
* 发布事件。
*
* @param eventName 事件名称
* @param args 传给监听器的参数
* @returns 各监听器的返回结果组成的数组
*/
public publish<X extends K>(eventName: X, ...args: ArgumentsType<T[X]>): Array<ReturnType<T[X]>> {
public emit<X extends K>(eventName: X, ...args: ArgumentsType<T[X]>): Array<ReturnType<T[X]>> {
return (this.listeners[eventName] || []).map(listener => {
return listener(...args)
})
Expand Down
27 changes: 16 additions & 11 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1352,40 +1352,45 @@ describe('EventBus', () => {
onceFn: () => void
}>()

test('publish 触发事件监听器且返回其值', () => {
test('emit 触发事件监听器且返回其值', () => {
const onClickUrl = jest.fn(() => 'clicked')
bus.subscribe('clickUrl', onClickUrl)
bus.on('clickUrl', onClickUrl)
vtils.range(0, 1000).forEach(i => {
expect(onClickUrl).toBeCalledTimes(i)
expect(bus.publish('clickUrl')).toEqual(['clicked'])
expect(bus.emit('clickUrl')).toEqual(['clicked'])
})
})

test('subscribeOnce 绑定的事件监听器只会触发一次', () => {
test('once 绑定的事件监听器只会触发一次', () => {
const onceFn = jest.fn()
expect(onceFn).toBeCalledTimes(0)
bus.subscribeOnce('onceFn', onceFn)
bus.once('onceFn', onceFn)
vtils.range(0, 1000).forEach(i => {
bus.publish('onceFn')
bus.emit('onceFn')
})
expect(onceFn).toBeCalledTimes(1)
})

test('可对同一事件绑定多个监听器,但相同的监听器只会绑定一次', () => {
bus.subscribe('add', (a, b) => {
bus.on('add', (a, b) => {
return a + b
})
const minus = (a: number, b: number): number => {
return a - b
}
bus.subscribe('add', minus)
bus.subscribe('add', minus)
bus.on('add', minus)
bus.on('add', minus)
vtils.range(0, 1000).forEach(i => {
expect(bus.publish('add', i, i + 1)).toEqual([i + i + 1, i - (i + 1)])
expect(bus.emit('add', i, i + 1)).toEqual([i + i + 1, i - (i + 1)])
})
})

test('未绑定的事件监听器返回空数组', () => {
expect(bus.publish('notFound' as any)).toEqual([])
expect(bus.emit('notFound' as any)).toEqual([])
})

test('取消事件的所有监听器', () => {
bus.off('add')
expect(bus.emit('add', 1, 2)).toEqual([])
})
})

0 comments on commit 1c43d87

Please sign in to comment.