Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ All notable changes to `hy-event-store` are documented in this file.

- Add first-party TypeScript declarations for event payloads, state keys,
actions, and action return values, plus compile-time regression coverage.
- Allow <code>off</code> to cancel a pending <code>once</code> listener by using
the original callback reference.

## 1.4.0 - 2026-08-19

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ store.offStates(["count", "status"], renderProfile)
| <code>on(eventName, callback, thisArg?)</code> | Register a listener. | The event bus |
| <code>once(eventName, callback, thisArg?)</code> | Register a listener removed before its first callback runs. | The event bus |
| <code>emit(eventName, ...payload)</code> | Notify every listener for an event. | The event bus |
| <code>off(eventName, callback)</code> | Remove registrations for the exact callback. It is safe when the event has no listeners. | The event bus |
| <code>off(eventName, callback)</code> | Remove registrations for the callback passed to <code>on</code> or <code>once</code>. It is safe when the event has no listeners. | The event bus |
| <code>clear()</code> | Remove listeners for every event. | The event bus |
| <code>hasEvent(eventName)</code> | Check whether an event has at least one listener. | Boolean |

Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ store.offStates(["count", "status"], renderProfile)
| <code>on(eventName, callback, thisArg?)</code> | 注册监听器。 | 事件总线实例 |
| <code>once(eventName, callback, thisArg?)</code> | 注册仅在第一次触发时执行的监听器。 | 事件总线实例 |
| <code>emit(eventName, ...payload)</code> | 通知某个事件的全部监听器。 | 事件总线实例 |
| <code>off(eventName, callback)</code> | 移除指定回调的监听;事件不存在时也可安全调用。 | 事件总线实例 |
| <code>off(eventName, callback)</code> | 移除通过 <code>on</code> 或 <code>once</code> 注册的回调;事件不存在时也可安全调用。 | 事件总线实例 |
| <code>clear()</code> | 清除全部事件的监听器。 | 事件总线实例 |
| <code>hasEvent(eventName)</code> | 判断事件是否至少有一个监听器。 | 布尔值 |

Expand Down
15 changes: 15 additions & 0 deletions Test/event-bus.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,21 @@ test("once does not skip the next handler", () => {
assert.deepEqual(calls, ["once", "always", "always"])
})

test("off cancels a once listener by its original callback", () => {
const bus = new HYEventBus()
let calls = 0
const callback = () => {
calls += 1
}

bus.once("update", callback)
bus.off("update", callback)
bus.emit("update")

assert.equal(calls, 0)
assert.equal(bus.hasEvent("update"), false)
})

test("off is safe for missing events and removes matching handlers", () => {
const bus = new HYEventBus()
const callback = () => {}
Expand Down
7 changes: 5 additions & 2 deletions src/event-bus.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class HYEventBus {

handlers.push({
eventCallback,
originalCallback: eventCallback,
thisArg
})
return this
Expand All @@ -39,7 +40,9 @@ class HYEventBus {
eventCallback.apply(thisArg, payload)
}

return this.on(eventName, tempCallback, thisArg)
this.on(eventName, tempCallback, thisArg)
this.eventBus[eventName][this.eventBus[eventName].length - 1].originalCallback = eventCallback
return this
}

emit(eventName, ...payload) {
Expand Down Expand Up @@ -70,7 +73,7 @@ class HYEventBus {
}

this.eventBus[eventName] = handlers.filter(handler => {
return handler.eventCallback !== eventCallback
return handler.eventCallback !== eventCallback && handler.originalCallback !== eventCallback
})

if (this.eventBus[eventName].length === 0) {
Expand Down