better code: event api to preventDefault and return value at the same time
Massimo Melina committed
Aug 26, 2024 at 11:45 UTC
6d53ea837006300941c303e5b9ee5390f8bfbbd1
3 files changed
+18
-10
src/cross.ts
-1
@@ -403,7 +403,6 @@ export function pathEncode(s: string) {
403
}
404
//unused function pathDecode(s: string) { return decodeURI(s).replace(/%23/g, '#') }
405
406
-
406
// run at a specific point in time, also solving the limit of setTimeout, which doesn't work with +32bit delays
407
export function runAt(ts: number, cb: Callback) {
408
let cancel = false
src/events.ts
+17
-8
@@ -6,7 +6,7 @@ const LISTENERS_SUFFIX = '\0listeners'
6
7
export class BetterEventEmitter {
8
protected listeners = new Map<string, Listeners>()
9
- stop = Symbol()
9
+ preventDefault = Symbol()
10
on(event: string | string[], listener: Listener, { warnAfter=10 }={}) {
11
if (typeof event === 'string')
12
event = [event]
@@ -51,19 +51,28 @@ export class BetterEventEmitter {
51
let cbs = this.listeners.get(event)
52
if (!cbs?.size) return
53
const ret: any[] = []
54
+ let prevented = false
55
+ const extra = {
56
+ preventDefault() { prevented = true }
57
+ }
58
for (const cb of cbs) {
55
- const res = cb(...args)
56
- if (res !== undefined)
59
+ const res = cb(...args, extra)
60
+ if (res === this.preventDefault)
61
+ extra.preventDefault()
62
+ else if (res !== undefined)
63
ret.push(res)
64
}
65
return Object.assign(ret, {
60
- isDefaultPrevented: () => ret.some(r => r === this.stop),
66
+ isDefaultPrevented: () => prevented,
67
})
68
}
63
- emitAsync(event: string, ...args: any[]) {
64
- const ret = Promise.all(this.emit(event, ...args) || [])
65
- return Object.assign(ret, {
66
- isDefaultPrevented: async () => (await ret).some((r: any) => r === this.stop)
69
+ async emitAsync(event: string, ...args: any[]) {
70
+ const syncRet = this.emit(event, ...args)
71
+ if (!syncRet) return
72
+ const asyncRet = await Promise.all(syncRet)
73
+ return Object.assign(asyncRet, {
74
+ isDefaultPrevented: () => syncRet.isDefaultPrevented()
75
+ || asyncRet.some((r: any) => r === this.preventDefault)
76
})
77
}
78
}
src/misc.ts
+1
-1
@@ -145,7 +145,7 @@ export async function deleteNode(ctx: Koa.Context, node: VfsNode, uri: string) {
145
if (statusCodeForMissingPerm(node, 'can_delete', ctx))
146
return ctx.status
147
try {
148
- if (await events.emitAsync('deleting', { node, ctx }).isDefaultPrevented())
148
+ if ((await events.emitAsync('deleting', { node, ctx }))?.isDefaultPrevented())
149
return null // stop
150
ctx.logExtra(null, { target: decodeURI(uri) })
151
await rm(source, { recursive: true })