Skip to content

Commit 5956445

Browse files
author
Pratik Bhattacharya
committed
fix: allowing multiple subscribers
1 parent ee62b9c commit 5956445

File tree

2 files changed

+82
-24
lines changed

2 files changed

+82
-24
lines changed

src/global.store.ts

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ export class GlobalStore implements IGlobalStore {
1919
private _stores: { [key: string]: Store };
2020
private _globalActions: { [key: string]: Array<string> };
2121
private _globalListeners: Array<(state: any) => void>;
22-
private _eagerPartnerStoreSubscribers: { [key: string]: (state: any) => void};
23-
private _eagerUnsubscribers: { [key: string]: () => void };
22+
private _eagerPartnerStoreSubscribers: { [key: string]: { [key: string]: (state) => void } }
23+
private _eagerUnsubscribers: { [key: string]: { [key: string]: () => void } }
2424
private _actionLogger: ActionLogger = null;
2525

2626
private constructor(private _logger: ILogger = null) {
@@ -38,7 +38,7 @@ export class GlobalStore implements IGlobalStore {
3838
* @param {ILogger} logger Logger service.
3939
*/
4040
public static Get(debugMode: boolean = false, logger: ILogger = null): IGlobalStore {
41-
if(debugMode) {
41+
if (debugMode) {
4242
this.DebugMode = debugMode;
4343
}
4444
if (debugMode && (logger === undefined || logger === null)) {
@@ -70,7 +70,7 @@ export class GlobalStore implements IGlobalStore {
7070
if (existingStore === null || existingStore === undefined || shouldReplaceStore) {
7171
if (middlewares === undefined || middlewares === null)
7272
middlewares = [];
73-
let appStore = createStore(appReducer, GlobalStore.DebugMode ? composeWithDevTools( applyMiddleware(...middlewares)) : applyMiddleware(...middlewares));
73+
let appStore = createStore(appReducer, GlobalStore.DebugMode ? composeWithDevTools(applyMiddleware(...middlewares)) : applyMiddleware(...middlewares));
7474
this.RegisterStore(appName, appStore, globalActions, shouldReplaceStore);
7575
return appStore;
7676
}
@@ -100,10 +100,7 @@ export class GlobalStore implements IGlobalStore {
100100
this._stores[appName] = store;
101101
store.subscribe(this.InvokeGlobalListeners.bind(this));
102102
this.RegisterGlobalActions(appName, globalActions);
103-
let eagerSubscription = this._eagerPartnerStoreSubscribers[appName];
104-
if (eagerSubscription !== undefined && eagerSubscription !== null){
105-
this._eagerUnsubscribers[appName] = this.SubscribeToPartnerState("SYS", appName, eagerSubscription);
106-
}
103+
this.RegisterEagerSubscriptions(appName);
107104
this.LogRegistration(appName, (existingStore !== undefined && existingStore !== null));
108105
}
109106

@@ -282,13 +279,19 @@ export class GlobalStore implements IGlobalStore {
282279
SubscribeToPartnerState(source: string, partner: string, callback: (state: any) => void, eager: boolean = true): () => void {
283280
let partnerStore = this.GetPartnerStore(partner);
284281
if (partnerStore === undefined || partnerStore === null) {
285-
if (!eager){
282+
if (!eager) {
286283
throw new Error(`ERROR: ${source} is trying to subscribe to partner ${partner}. Either ${partner} doesn't exist or hasn't been loaded yet`);
287284
}
288-
289-
this._eagerPartnerStoreSubscribers[partner] = callback;
285+
if (this._eagerPartnerStoreSubscribers[partner]) {
286+
this._eagerPartnerStoreSubscribers[partner].source = callback;
287+
} else {
288+
this._eagerPartnerStoreSubscribers[partner] = {
289+
source: callback
290+
}
291+
}
292+
290293
return () => {
291-
this.UnsubscribeEagerSubscription(partner);
294+
this.UnsubscribeEagerSubscription(source, partner);
292295
}
293296
}
294297
return partnerStore.subscribe(() => callback(partnerStore.getState()));
@@ -311,6 +314,18 @@ export class GlobalStore implements IGlobalStore {
311314
}
312315
}
313316

317+
UnsubscribeEagerSubscription(source: string, partnerName: string) {
318+
if (!partnerName || !source)
319+
return;
320+
321+
if (!this._eagerUnsubscribers[partnerName])
322+
return;
323+
324+
let unsubscriber = this._eagerUnsubscribers[partnerName].source;
325+
if (unsubscriber)
326+
unsubscriber();
327+
}
328+
314329
SetLogger(logger: ILogger) {
315330
if (this._logger === undefined || this._logger === null)
316331
this._logger = logger;
@@ -319,6 +334,26 @@ export class GlobalStore implements IGlobalStore {
319334
this._actionLogger.SetLogger(logger);
320335
}
321336

337+
private RegisterEagerSubscriptions(appName: string) {
338+
let eagerCallbacksRegistrations = this._eagerPartnerStoreSubscribers[appName];
339+
if (eagerCallbacksRegistrations === undefined || eagerCallbacksRegistrations === undefined)
340+
return;
341+
let registeredApps = Object.keys(eagerCallbacksRegistrations);
342+
registeredApps.forEach(sourceApp => {
343+
let callback = eagerCallbacksRegistrations[sourceApp];
344+
if (callback) {
345+
let unregistrationCallback = this.SubscribeToPartnerState(sourceApp, appName, callback, false);
346+
if (this._eagerPartnerStoreSubscribers[appName]) {
347+
this._eagerPartnerStoreSubscribers[appName].sourceApp = unregistrationCallback;
348+
} else {
349+
this._eagerPartnerStoreSubscribers[appName] = {
350+
sourceApp: unregistrationCallback
351+
};
352+
}
353+
}
354+
});
355+
}
356+
322357
private InvokeGlobalListeners(): void {
323358
let globalState = this.GetGlobalState();
324359
this._globalListeners.forEach(globalListener => {
@@ -341,21 +376,12 @@ export class GlobalStore implements IGlobalStore {
341376

342377
private IsActionRegisteredAsGlobal(appName: string, action: IAction<any>): boolean {
343378
let registeredGlobalActions = this._globalActions[appName];
344-
if (registeredGlobalActions === undefined || registeredGlobalActions === null) {
345-
return false;
346-
}
379+
if (registeredGlobalActions === undefined || registeredGlobalActions === null) {
380+
return false;
381+
}
347382
return registeredGlobalActions.some(registeredAction => registeredAction === action.type || registeredAction === GlobalStore.AllowAll);
348383
}
349384

350-
private UnsubscribeEagerSubscription(partnerName: string) {
351-
if (!partnerName)
352-
return;
353-
354-
let unsubscriber = this._eagerUnsubscribers[partnerName];
355-
if (unsubscriber)
356-
unsubscriber();
357-
}
358-
359385
private LogRegistration(appName: string, isReplaced: boolean) {
360386
try {
361387
let properties = {

test/global.store.tests.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ describe("Global Store", () => {
358358
// Arrange
359359
let partnerAppName = "SamplePartner-102";
360360
let isPartnerStateChanged = false;
361+
361362
// Act
362363
globalStore.SubscribeToPartnerState("Test", partnerAppName, (state) => {
363364
isPartnerStateChanged = true;
@@ -374,6 +375,37 @@ describe("Global Store", () => {
374375
// Assert
375376
expect(isPartnerStateChanged).toBeTruthy();
376377
});
378+
379+
it("Should attach eager multiple subscribers", () => {
380+
// Arrange
381+
let partnerAppName_1 = "SamplePartner-112";
382+
let isPartnerStateChanged_1 = false;
383+
384+
let partnerAppName_2 = "SamplePartner-114";
385+
let isPartnerStateChanged_2 = false;
386+
387+
// Act
388+
globalStore.SubscribeToPartnerState("Test", partnerAppName_1, (state) => {
389+
isPartnerStateChanged_1 = true;
390+
}, true);
391+
392+
globalStore.SubscribeToPartnerState("Test", partnerAppName_2, (state) => {
393+
isPartnerStateChanged_2 = true;
394+
}, true);
395+
396+
globalStore.CreateStore(partnerAppName_1, dummyPartnerReducer, [], ["Global"], false, false);
397+
globalStore.CreateStore(partnerAppName_2, dummyPartnerReducer, [], ["Global"], false, false);
398+
globalStore.DispatchGlobalAction("Test",
399+
{
400+
type: "Global",
401+
payload: null
402+
});
403+
404+
405+
// Assert
406+
expect(isPartnerStateChanged_1).toBeTruthy();
407+
expect(isPartnerStateChanged_2).toBeTruthy();
408+
});
377409
});
378410

379411
describe("SubscribeToGlobalState", () => {

0 commit comments

Comments
 (0)