@norcy/react-native-toolkit 0.2.15 → 0.2.16
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.
|
@@ -6,32 +6,53 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.Notification = void 0;
|
|
7
7
|
const EventEmitter = require('events').EventEmitter;
|
|
8
8
|
const eventEmitter = new EventEmitter();
|
|
9
|
-
const
|
|
9
|
+
const callbackToEvent = new WeakMap();
|
|
10
|
+
const isCallbackRegistered = (callback, event) => {
|
|
11
|
+
return eventEmitter.listeners(event).includes(callback);
|
|
12
|
+
};
|
|
10
13
|
const Notification = exports.Notification = {
|
|
11
14
|
addListener: (event, callback, skipCache) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
if (!skipCache) {
|
|
16
|
+
const existingEvent = callbackToEvent.get(callback);
|
|
17
|
+
if (existingEvent && isCallbackRegistered(callback, existingEvent)) {
|
|
18
|
+
if (existingEvent === event) {
|
|
19
|
+
return callback;
|
|
20
|
+
}
|
|
21
|
+
// 本类的设计只允许,同一个 callback 对应一个 eventKey,不允许多个 eventKey 对应同一个 callback
|
|
22
|
+
// Notification.addListener('Theme_Update', callback); // ✅ 成功
|
|
23
|
+
// Notification.addListener('Theme_Update', callback); // ✅ 跳过,返回 callback
|
|
24
|
+
// Notification.addListener('Language_Update', callback); // ❌ 抛错!
|
|
25
|
+
throw new Error(`[Notification] callback 已注册到事件 "${existingEvent}",不能重复注册到 "${event}"`);
|
|
26
|
+
}
|
|
16
27
|
}
|
|
28
|
+
eventEmitter.on(event, callback);
|
|
29
|
+
callbackToEvent.set(callback, event);
|
|
17
30
|
return callback;
|
|
18
31
|
},
|
|
19
32
|
addListenerOnce: (event, callback) => {
|
|
20
33
|
eventEmitter.once(event, callback);
|
|
21
34
|
},
|
|
22
35
|
removeListener: callback => {
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
delete ListenerToEvent[key];
|
|
36
|
+
const event = callbackToEvent.get(callback);
|
|
37
|
+
if (!event) return;
|
|
26
38
|
eventEmitter.removeListener(event, callback);
|
|
39
|
+
callbackToEvent.delete(callback);
|
|
27
40
|
},
|
|
28
41
|
removeAllListeners: event => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
42
|
+
// 只清理 EventEmitter,不清理 callbackToEvent(残留 callback -> event 映射)
|
|
43
|
+
// 不清理原因:WeakMap 无法反向查找,清理需维护额外映射(复杂度高,不值得)
|
|
44
|
+
// 残留无任何影响:
|
|
45
|
+
// 1. 内存:WeakMap 弱引用,callback 被 GC 后自动清理,无泄漏
|
|
46
|
+
// 2. removeListener:即使 eventEmitter 中已无此 callback,removeListener 调用也安全
|
|
47
|
+
// 3. postNotification:真正的 callback 已经从 eventEmitter 中移除,不会被调用
|
|
48
|
+
// 4. 逻辑:addListener 通过 isCallbackRegistered 双重检查,脏数据不影响判断,如下
|
|
49
|
+
// 例:addListener('A', cb) 后调用 removeAllListeners('A')
|
|
50
|
+
// - eventEmitter 中 cb 已被移除
|
|
51
|
+
// - callbackToEvent 仍记录 cb -> 'A'(脏数据)
|
|
52
|
+
//
|
|
53
|
+
// 后续 addListener('A', cb) 时:
|
|
54
|
+
// - callbackToEvent.get(cb) 返回 'A'
|
|
55
|
+
// - isCallbackRegistered(cb, 'A') 检查 eventEmitter.listeners('A'),发现 cb 不在,会重新更新 Map 并注册
|
|
35
56
|
eventEmitter.removeAllListeners(event);
|
|
36
57
|
},
|
|
37
58
|
postNotification: (event, args) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["EventEmitter","require","eventEmitter","
|
|
1
|
+
{"version":3,"names":["EventEmitter","require","eventEmitter","callbackToEvent","WeakMap","isCallbackRegistered","callback","event","listeners","includes","Notification","exports","addListener","skipCache","existingEvent","get","Error","on","set","addListenerOnce","once","removeListener","delete","removeAllListeners","postNotification","args","emit"],"sourceRoot":"../../src","sources":["Notification.ts"],"mappings":";;;;;;AAAA,MAAMA,YAAY,GAAGC,OAAO,CAAC,QAAQ,CAAC,CAACD,YAAY;AACnD,MAAME,YAAY,GAAG,IAAIF,YAAY,CAAC,CAAC;AAEvC,MAAMG,eAAe,GAAG,IAAIC,OAAO,CAAmB,CAAC;AAEvD,MAAMC,oBAAoB,GAAGA,CAACC,QAAkB,EAAEC,KAAa,KAAc;EAC3E,OAAOL,YAAY,CAACM,SAAS,CAACD,KAAK,CAAC,CAACE,QAAQ,CAACH,QAAQ,CAAC;AACzD,CAAC;AAEM,MAAMI,YAAY,GAAAC,OAAA,CAAAD,YAAA,GAAG;EAC1BE,WAAW,EAAEA,CAACL,KAAa,EAAED,QAAkB,EAAEO,SAAmB,KAAK;IACvE,IAAI,CAACA,SAAS,EAAE;MACd,MAAMC,aAAa,GAAGX,eAAe,CAACY,GAAG,CAACT,QAAQ,CAAC;MAEnD,IAAIQ,aAAa,IAAIT,oBAAoB,CAACC,QAAQ,EAAEQ,aAAa,CAAC,EAAE;QAClE,IAAIA,aAAa,KAAKP,KAAK,EAAE;UAC3B,OAAOD,QAAQ;QACjB;QACA;QACA;QACA;QACA;QACA,MAAM,IAAIU,KAAK,CACb,mCAAmCF,aAAa,cAAcP,KAAK,GACrE,CAAC;MACH;IACF;IAEAL,YAAY,CAACe,EAAE,CAACV,KAAK,EAAED,QAAQ,CAAC;IAChCH,eAAe,CAACe,GAAG,CAACZ,QAAQ,EAAEC,KAAK,CAAC;IACpC,OAAOD,QAAQ;EACjB,CAAC;EAEDa,eAAe,EAAEA,CAACZ,KAAa,EAAED,QAAkB,KAAK;IACtDJ,YAAY,CAACkB,IAAI,CAACb,KAAK,EAAED,QAAQ,CAAC;EACpC,CAAC;EAEDe,cAAc,EAAGf,QAAkB,IAAK;IACtC,MAAMC,KAAK,GAAGJ,eAAe,CAACY,GAAG,CAACT,QAAQ,CAAC;IAC3C,IAAI,CAACC,KAAK,EAAE;IAEZL,YAAY,CAACmB,cAAc,CAACd,KAAK,EAAED,QAAQ,CAAC;IAC5CH,eAAe,CAACmB,MAAM,CAAChB,QAAQ,CAAC;EAClC,CAAC;EAEDiB,kBAAkB,EAAGhB,KAAa,IAAK;IACrC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACAL,YAAY,CAACqB,kBAAkB,CAAChB,KAAK,CAAC;EACxC,CAAC;EAEDiB,gBAAgB,EAAEA,CAACjB,KAAa,EAAEkB,IAAa,KAAK;IAClDvB,YAAY,CAACwB,IAAI,CAACnB,KAAK,EAAEkB,IAAI,CAAC;EAChC;AACF,CAAC","ignoreList":[]}
|
|
@@ -2,32 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
const EventEmitter = require('events').EventEmitter;
|
|
4
4
|
const eventEmitter = new EventEmitter();
|
|
5
|
-
const
|
|
5
|
+
const callbackToEvent = new WeakMap();
|
|
6
|
+
const isCallbackRegistered = (callback, event) => {
|
|
7
|
+
return eventEmitter.listeners(event).includes(callback);
|
|
8
|
+
};
|
|
6
9
|
export const Notification = {
|
|
7
10
|
addListener: (event, callback, skipCache) => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
if (!skipCache) {
|
|
12
|
+
const existingEvent = callbackToEvent.get(callback);
|
|
13
|
+
if (existingEvent && isCallbackRegistered(callback, existingEvent)) {
|
|
14
|
+
if (existingEvent === event) {
|
|
15
|
+
return callback;
|
|
16
|
+
}
|
|
17
|
+
// 本类的设计只允许,同一个 callback 对应一个 eventKey,不允许多个 eventKey 对应同一个 callback
|
|
18
|
+
// Notification.addListener('Theme_Update', callback); // ✅ 成功
|
|
19
|
+
// Notification.addListener('Theme_Update', callback); // ✅ 跳过,返回 callback
|
|
20
|
+
// Notification.addListener('Language_Update', callback); // ❌ 抛错!
|
|
21
|
+
throw new Error(`[Notification] callback 已注册到事件 "${existingEvent}",不能重复注册到 "${event}"`);
|
|
22
|
+
}
|
|
12
23
|
}
|
|
24
|
+
eventEmitter.on(event, callback);
|
|
25
|
+
callbackToEvent.set(callback, event);
|
|
13
26
|
return callback;
|
|
14
27
|
},
|
|
15
28
|
addListenerOnce: (event, callback) => {
|
|
16
29
|
eventEmitter.once(event, callback);
|
|
17
30
|
},
|
|
18
31
|
removeListener: callback => {
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
delete ListenerToEvent[key];
|
|
32
|
+
const event = callbackToEvent.get(callback);
|
|
33
|
+
if (!event) return;
|
|
22
34
|
eventEmitter.removeListener(event, callback);
|
|
35
|
+
callbackToEvent.delete(callback);
|
|
23
36
|
},
|
|
24
37
|
removeAllListeners: event => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
38
|
+
// 只清理 EventEmitter,不清理 callbackToEvent(残留 callback -> event 映射)
|
|
39
|
+
// 不清理原因:WeakMap 无法反向查找,清理需维护额外映射(复杂度高,不值得)
|
|
40
|
+
// 残留无任何影响:
|
|
41
|
+
// 1. 内存:WeakMap 弱引用,callback 被 GC 后自动清理,无泄漏
|
|
42
|
+
// 2. removeListener:即使 eventEmitter 中已无此 callback,removeListener 调用也安全
|
|
43
|
+
// 3. postNotification:真正的 callback 已经从 eventEmitter 中移除,不会被调用
|
|
44
|
+
// 4. 逻辑:addListener 通过 isCallbackRegistered 双重检查,脏数据不影响判断,如下
|
|
45
|
+
// 例:addListener('A', cb) 后调用 removeAllListeners('A')
|
|
46
|
+
// - eventEmitter 中 cb 已被移除
|
|
47
|
+
// - callbackToEvent 仍记录 cb -> 'A'(脏数据)
|
|
48
|
+
//
|
|
49
|
+
// 后续 addListener('A', cb) 时:
|
|
50
|
+
// - callbackToEvent.get(cb) 返回 'A'
|
|
51
|
+
// - isCallbackRegistered(cb, 'A') 检查 eventEmitter.listeners('A'),发现 cb 不在,会重新更新 Map 并注册
|
|
31
52
|
eventEmitter.removeAllListeners(event);
|
|
32
53
|
},
|
|
33
54
|
postNotification: (event, args) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["EventEmitter","require","eventEmitter","
|
|
1
|
+
{"version":3,"names":["EventEmitter","require","eventEmitter","callbackToEvent","WeakMap","isCallbackRegistered","callback","event","listeners","includes","Notification","addListener","skipCache","existingEvent","get","Error","on","set","addListenerOnce","once","removeListener","delete","removeAllListeners","postNotification","args","emit"],"sourceRoot":"../../src","sources":["Notification.ts"],"mappings":";;AAAA,MAAMA,YAAY,GAAGC,OAAO,CAAC,QAAQ,CAAC,CAACD,YAAY;AACnD,MAAME,YAAY,GAAG,IAAIF,YAAY,CAAC,CAAC;AAEvC,MAAMG,eAAe,GAAG,IAAIC,OAAO,CAAmB,CAAC;AAEvD,MAAMC,oBAAoB,GAAGA,CAACC,QAAkB,EAAEC,KAAa,KAAc;EAC3E,OAAOL,YAAY,CAACM,SAAS,CAACD,KAAK,CAAC,CAACE,QAAQ,CAACH,QAAQ,CAAC;AACzD,CAAC;AAED,OAAO,MAAMI,YAAY,GAAG;EAC1BC,WAAW,EAAEA,CAACJ,KAAa,EAAED,QAAkB,EAAEM,SAAmB,KAAK;IACvE,IAAI,CAACA,SAAS,EAAE;MACd,MAAMC,aAAa,GAAGV,eAAe,CAACW,GAAG,CAACR,QAAQ,CAAC;MAEnD,IAAIO,aAAa,IAAIR,oBAAoB,CAACC,QAAQ,EAAEO,aAAa,CAAC,EAAE;QAClE,IAAIA,aAAa,KAAKN,KAAK,EAAE;UAC3B,OAAOD,QAAQ;QACjB;QACA;QACA;QACA;QACA;QACA,MAAM,IAAIS,KAAK,CACb,mCAAmCF,aAAa,cAAcN,KAAK,GACrE,CAAC;MACH;IACF;IAEAL,YAAY,CAACc,EAAE,CAACT,KAAK,EAAED,QAAQ,CAAC;IAChCH,eAAe,CAACc,GAAG,CAACX,QAAQ,EAAEC,KAAK,CAAC;IACpC,OAAOD,QAAQ;EACjB,CAAC;EAEDY,eAAe,EAAEA,CAACX,KAAa,EAAED,QAAkB,KAAK;IACtDJ,YAAY,CAACiB,IAAI,CAACZ,KAAK,EAAED,QAAQ,CAAC;EACpC,CAAC;EAEDc,cAAc,EAAGd,QAAkB,IAAK;IACtC,MAAMC,KAAK,GAAGJ,eAAe,CAACW,GAAG,CAACR,QAAQ,CAAC;IAC3C,IAAI,CAACC,KAAK,EAAE;IAEZL,YAAY,CAACkB,cAAc,CAACb,KAAK,EAAED,QAAQ,CAAC;IAC5CH,eAAe,CAACkB,MAAM,CAACf,QAAQ,CAAC;EAClC,CAAC;EAEDgB,kBAAkB,EAAGf,KAAa,IAAK;IACrC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACAL,YAAY,CAACoB,kBAAkB,CAACf,KAAK,CAAC;EACxC,CAAC;EAEDgB,gBAAgB,EAAEA,CAAChB,KAAa,EAAEiB,IAAa,KAAK;IAClDtB,YAAY,CAACuB,IAAI,CAAClB,KAAK,EAAEiB,IAAI,CAAC;EAChC;AACF,CAAC","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Notification.d.ts","sourceRoot":"","sources":["../../src/Notification.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,YAAY;yBACF,MAAM,YAAY,QAAQ,cAAc,OAAO;
|
|
1
|
+
{"version":3,"file":"Notification.d.ts","sourceRoot":"","sources":["../../src/Notification.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,YAAY;yBACF,MAAM,YAAY,QAAQ,cAAc,OAAO;6BAuB3C,MAAM,YAAY,QAAQ;+BAIxB,QAAQ;gCAQP,MAAM;8BAkBR,MAAM,SAAS,MAAM;CAGhD,CAAC"}
|
package/package.json
CHANGED
package/src/Notification.ts
CHANGED
|
@@ -1,19 +1,33 @@
|
|
|
1
1
|
const EventEmitter = require('events').EventEmitter;
|
|
2
2
|
const eventEmitter = new EventEmitter();
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
[key: string]: string;
|
|
6
|
-
}
|
|
4
|
+
const callbackToEvent = new WeakMap<Function, string>();
|
|
7
5
|
|
|
8
|
-
const
|
|
6
|
+
const isCallbackRegistered = (callback: Function, event: string): boolean => {
|
|
7
|
+
return eventEmitter.listeners(event).includes(callback);
|
|
8
|
+
};
|
|
9
9
|
|
|
10
10
|
export const Notification = {
|
|
11
11
|
addListener: (event: string, callback: Function, skipCache?: boolean) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
if (!skipCache) {
|
|
13
|
+
const existingEvent = callbackToEvent.get(callback);
|
|
14
|
+
|
|
15
|
+
if (existingEvent && isCallbackRegistered(callback, existingEvent)) {
|
|
16
|
+
if (existingEvent === event) {
|
|
17
|
+
return callback;
|
|
18
|
+
}
|
|
19
|
+
// 本类的设计只允许,同一个 callback 对应一个 eventKey,不允许多个 eventKey 对应同一个 callback
|
|
20
|
+
// Notification.addListener('Theme_Update', callback); // ✅ 成功
|
|
21
|
+
// Notification.addListener('Theme_Update', callback); // ✅ 跳过,返回 callback
|
|
22
|
+
// Notification.addListener('Language_Update', callback); // ❌ 抛错!
|
|
23
|
+
throw new Error(
|
|
24
|
+
`[Notification] callback 已注册到事件 "${existingEvent}",不能重复注册到 "${event}"`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
16
27
|
}
|
|
28
|
+
|
|
29
|
+
eventEmitter.on(event, callback);
|
|
30
|
+
callbackToEvent.set(callback, event);
|
|
17
31
|
return callback;
|
|
18
32
|
},
|
|
19
33
|
|
|
@@ -22,19 +36,28 @@ export const Notification = {
|
|
|
22
36
|
},
|
|
23
37
|
|
|
24
38
|
removeListener: (callback: Function) => {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
39
|
+
const event = callbackToEvent.get(callback);
|
|
40
|
+
if (!event) return;
|
|
41
|
+
|
|
28
42
|
eventEmitter.removeListener(event, callback);
|
|
43
|
+
callbackToEvent.delete(callback);
|
|
29
44
|
},
|
|
30
45
|
|
|
31
46
|
removeAllListeners: (event: string) => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
47
|
+
// 只清理 EventEmitter,不清理 callbackToEvent(残留 callback -> event 映射)
|
|
48
|
+
// 不清理原因:WeakMap 无法反向查找,清理需维护额外映射(复杂度高,不值得)
|
|
49
|
+
// 残留无任何影响:
|
|
50
|
+
// 1. 内存:WeakMap 弱引用,callback 被 GC 后自动清理,无泄漏
|
|
51
|
+
// 2. removeListener:即使 eventEmitter 中已无此 callback,removeListener 调用也安全
|
|
52
|
+
// 3. postNotification:真正的 callback 已经从 eventEmitter 中移除,不会被调用
|
|
53
|
+
// 4. 逻辑:addListener 通过 isCallbackRegistered 双重检查,脏数据不影响判断,如下
|
|
54
|
+
// 例:addListener('A', cb) 后调用 removeAllListeners('A')
|
|
55
|
+
// - eventEmitter 中 cb 已被移除
|
|
56
|
+
// - callbackToEvent 仍记录 cb -> 'A'(脏数据)
|
|
57
|
+
//
|
|
58
|
+
// 后续 addListener('A', cb) 时:
|
|
59
|
+
// - callbackToEvent.get(cb) 返回 'A'
|
|
60
|
+
// - isCallbackRegistered(cb, 'A') 检查 eventEmitter.listeners('A'),发现 cb 不在,会重新更新 Map 并注册
|
|
38
61
|
eventEmitter.removeAllListeners(event);
|
|
39
62
|
},
|
|
40
63
|
|