grofc_utils 1.6.1 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/event.js +38 -29
package/package.json
CHANGED
package/src/event.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isPlainObject, throwIfIsNotExpectedValue, throwIfIsNotFunction, throwIfIsNotPlainObject, throwIfIsNotString } from "./guard.js"
|
|
1
|
+
import { isPlainObject, throwIfIsNotExpectedValue, throwIfIsNotFunction, throwIfIsNotPlainObject, throwIfIsNotString, throwIfSomeKeysMissing } from "./guard.js"
|
|
2
2
|
import { assignWithDescriptors } from "./object.js";
|
|
3
3
|
import { randomString } from "./random.js";
|
|
4
4
|
|
|
@@ -15,18 +15,43 @@ import { randomString } from "./random.js";
|
|
|
15
15
|
* )=>object
|
|
16
16
|
* on:(event:string,phase:"before"|"begin"|"end"|"after",{
|
|
17
17
|
* name:string
|
|
18
|
-
* filter
|
|
18
|
+
* filter?:(event:{
|
|
19
19
|
* target,name:string,type:string|null,preData:object,data:object
|
|
20
20
|
* })
|
|
21
21
|
* callback:(event:{
|
|
22
22
|
* target,name:string,type:string|null,preData:object,data:object
|
|
23
23
|
* })=>void
|
|
24
|
+
* once?:boolean
|
|
24
25
|
* })=>void
|
|
25
26
|
* off:(event:string,phase:"before"|"begin"|"end"|"after",name:string)=>void
|
|
26
27
|
* }} 包含dispatchSync, on, off方法的对象
|
|
27
28
|
*/
|
|
28
29
|
export function createEventEmitter() {
|
|
29
30
|
const listenerMap = new Map()
|
|
31
|
+
const on = (event, phase, listener = {}) => {
|
|
32
|
+
throwIfIsNotString(event, "event");
|
|
33
|
+
throwIfIsNotExpectedValue(phase, "phase", "before", "begin", "end", "after");
|
|
34
|
+
throwIfSomeKeysMissing(listener, ["name", "callback"], "listener")
|
|
35
|
+
const eventName = event + ":" + phase;
|
|
36
|
+
const listenerList = listenerMap.get(eventName)
|
|
37
|
+
if (Array.isArray(listenerList)) {
|
|
38
|
+
listenerList.push(listener)
|
|
39
|
+
} else {
|
|
40
|
+
listenerMap.set(eventName, [listener]);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const off = (event, phase, name) => {
|
|
44
|
+
throwIfIsNotString(event, "event");
|
|
45
|
+
throwIfIsNotExpectedValue(phase, "phase", "before", "begin", "end", "after");
|
|
46
|
+
throwIfIsNotString(name, "name")
|
|
47
|
+
const eventName = event + ":" + phase;
|
|
48
|
+
const list = listenerMap.get(eventName);
|
|
49
|
+
if (Array.isArray(list)) {
|
|
50
|
+
const index = list.findIndex(o => o.name === name)
|
|
51
|
+
if (index !== -1) list.splice(index, 1);
|
|
52
|
+
if (list.length === 0) listenerMap.delete(eventName);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
30
55
|
const dispatchSync = (event, ing = () => { }, options = {}) => {
|
|
31
56
|
throwIfIsNotString(event, "event");
|
|
32
57
|
throwIfIsNotFunction(ing, "ing");
|
|
@@ -63,9 +88,11 @@ export function createEventEmitter() {
|
|
|
63
88
|
}
|
|
64
89
|
}, baseEvent)
|
|
65
90
|
const beforeListenerList = listenerMap.get(event + ":before") ?? [];
|
|
66
|
-
for (const { filter, callback } of beforeListenerList) {
|
|
91
|
+
for (const { name, filter, callback, once } of beforeListenerList.slice()) {
|
|
67
92
|
if (filter?.(beforeEvent) === false) continue;
|
|
68
|
-
|
|
93
|
+
const toCancel = callback(beforeEvent);
|
|
94
|
+
if (once) off(event, "before", name)
|
|
95
|
+
if (toCancel === false && beforeEvent.status.cancellable) return;
|
|
69
96
|
}
|
|
70
97
|
// 触发begin阶段监听器
|
|
71
98
|
const beginEvent = assignWithDescriptors({
|
|
@@ -74,9 +101,10 @@ export function createEventEmitter() {
|
|
|
74
101
|
}
|
|
75
102
|
}, baseEvent);
|
|
76
103
|
const beginListenerList = listenerMap.get(event + ":begin") ?? [];
|
|
77
|
-
for (const { callback, filter } of beginListenerList) {
|
|
104
|
+
for (const { name, callback, filter, once } of beginListenerList.slice()) {
|
|
78
105
|
if (filter?.(beginEvent) === false) continue;
|
|
79
106
|
callback(beginEvent)
|
|
107
|
+
if (once) off(event, "begin", name)
|
|
80
108
|
}
|
|
81
109
|
// 执行ing阶段函数并获取当前数据
|
|
82
110
|
const ingEvent = assignWithDescriptors({
|
|
@@ -96,9 +124,10 @@ export function createEventEmitter() {
|
|
|
96
124
|
}
|
|
97
125
|
}, baseEvent)
|
|
98
126
|
const endListenerList = listenerMap.get(event + ":end") ?? []
|
|
99
|
-
for (const { callback, filter } of endListenerList) {
|
|
127
|
+
for (const { name, callback, filter, once } of endListenerList.slice()) {
|
|
100
128
|
if (filter?.(endEvent) === false) continue;
|
|
101
129
|
callback(endEvent)
|
|
130
|
+
if (once) off(event, "end", name)
|
|
102
131
|
}
|
|
103
132
|
// 触发after阶段监听器,并处理可能的递归事件调用
|
|
104
133
|
const afterEvent = assignWithDescriptors({
|
|
@@ -110,37 +139,17 @@ export function createEventEmitter() {
|
|
|
110
139
|
}
|
|
111
140
|
}, baseEvent);
|
|
112
141
|
const afterListenerList = listenerMap.get(event + ":after") ?? [];
|
|
113
|
-
for (const { callback, filter } of afterListenerList) {
|
|
142
|
+
for (const { name, callback, filter, once } of afterListenerList.slice()) {
|
|
114
143
|
if (filter?.(afterEvent) === false) continue;
|
|
115
144
|
const result = callback(afterEvent)
|
|
145
|
+
if (once) off(event, "after", name)
|
|
116
146
|
if (!isPlainObject(result)) continue;
|
|
117
147
|
const { event, ing, options } = result;
|
|
118
148
|
if (typeof event !== "string") continue;
|
|
119
149
|
dispatchSync(event, ing, options)
|
|
120
150
|
}
|
|
121
151
|
}
|
|
122
|
-
|
|
123
|
-
throwIfIsNotString(event, "event");
|
|
124
|
-
throwIfIsNotExpectedValue(phase, "phase", "before", "begin", "end", "after");
|
|
125
|
-
const eventName = event + ":" + phase;
|
|
126
|
-
const listenerList = listenerMap.get(eventName)
|
|
127
|
-
if (Array.isArray(listenerList)) {
|
|
128
|
-
listenerList.push(listener)
|
|
129
|
-
} else {
|
|
130
|
-
listenerMap.set(eventName, [listener]);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
const off = (event, phase, name) => {
|
|
134
|
-
throwIfIsNotString(event, "event");
|
|
135
|
-
throwIfIsNotExpectedValue(phase, "phase", "before", "begin", "end", "after");
|
|
136
|
-
const eventName = event + ":" + phase;
|
|
137
|
-
const list = listenerMap.get(eventName);
|
|
138
|
-
if (Array.isArray(list)) {
|
|
139
|
-
const index = list.findIndex(o => o.name === name)
|
|
140
|
-
if (index !== -1) list.splice(index, 1);
|
|
141
|
-
if (list.length === 0) listenerMap.delete(eventName);
|
|
142
|
-
}
|
|
143
|
-
};
|
|
152
|
+
|
|
144
153
|
return {
|
|
145
154
|
dispatchSync,
|
|
146
155
|
on,
|