Skip to content

Instantly share code, notes, and snippets.

@otonii
Last active December 5, 2023 22:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save otonii/0f91421841aa667aa2beb9963945ac50 to your computer and use it in GitHub Desktop.
Save otonii/0f91421841aa667aa2beb9963945ac50 to your computer and use it in GitHub Desktop.
Abstract Subscribable Controller with reducer
type Fn = (...args: any[]) => any;
type Reducer = Record<string, Fn>;
type Unsubscribe = () => void;
let seed = 0;
export abstract class AbstractSubscribableController<TReducer extends Reducer> {
protected observers: Map<number, TReducer> = new Map();
subscribe(reducer: TReducer): Unsubscribe {
seed++;
this.observers.set(seed, reducer);
// Retornando o unsubscribe
return () => {
this.observers.delete(seed);
};
}
// Aqui pode ter o nome que quiser: dispatch, emit, notify, etc
dispatch<K extends keyof TReducer>(event: K, ...args: Parameters<TReducer[K]>) {
this.observers.forEach((observer) => observer[event]?.(...args));
}
}
class TestControllerImpl extends AbstractSubscribableController<TestReducer> implements TestController {
constructor() {
super();
}
public method1() {
try {
this.dispatch('onLoad');
// ...
this.dispatch('onSuccess', {
items: ['olá', 'mundo'],
flag: false
});
} catch (error) {
if (error instanceof Error) {
this.dispatch('onError', error.message);
}
}
}
public method2() {
// Se vc definir um reducer com mais de parâmetro é assim que seta os valores
this.dispatch('onTest', true, 'teste');
}
}
type SuccessState = {
items: string[];
flag: boolean;
}
export type TestReducer = {
onSuccess: (state: SuccessState) => void;
onError: (message: string) => void;
onLoad: () => void;
onTest: (loading: boolean, message: string) => void;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment