Skip to content

Instantly share code, notes, and snippets.

@kkoziarski
Last active February 20, 2018 08:11
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 kkoziarski/4d8482ac90048451ac94183ea7befdf3 to your computer and use it in GitHub Desktop.
Save kkoziarski/4d8482ac90048451ac94183ea7befdf3 to your computer and use it in GitHub Desktop.
Subscribe with unsubscribe listeners
// https://github.com/ng-book/angular2-redux-chat/blob/master/tutorial/06b-rx-store.ts
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/scan';
interface Action {
type: string;
payload?: any;
}
class Store<T> extends BehaviorSubject<T> {
private _dispatcher: Subject<Action>;
constructor(
initialState: T
) {
super(initialState);
this._dispatcher = new Subject<Action>();
this._dispatcher
.scan(
(state: T, action: Action) => /*TODO: this._reducer(state, action)*/,
initialState)
.subscribe((state) => super.emit(state));
}
getState(): T {
return this.value;
}
dispatch(action: Action): void {
this._dispatcher.emit(action);
}
}
// create a new store
console.log('-- store --');
let store = new Store<number>(0);
console.log(store.getState()); // -> 0
store.dispatch({ type: 'INCREMENT' });
console.log(store.getState()); // -> 1
store.dispatch({ type: 'INCREMENT' });
console.log(store.getState()); // -> 2
store.dispatch({ type: 'DECREMENT' });
console.log(store.getState()); // -> 1
// observing!
console.log('-- store2 --');
let store2 = new Store<number>(0);
store2.subscribe((newState => console.log("state: ", newState))); // -> state: 0
store2.dispatch({ type: 'INCREMENT' }); // -> state: 1
store2.dispatch({ type: 'INCREMENT' }); // -> state: 2
store2.dispatch({ type: 'DECREMENT' }); // -> state: 1
// https://github.com/ng-book/angular2-redux-chat/blob/master/tutorial/05-minimal-store.ts
interface Action {
type: string;
payload?: any;
}
interface ListenerCallback {
(): void;
}
interface UnsubscribeCallback {
(): void;
}
class Store<T> {
private _state: T;
private _listeners: ListenerCallback[] = [];
constructor(
initialState: T
) {
this._state = initialState;
}
getState(): T {
return this._state;
}
dispatch(action: Action): void {
// do something on this._state...
// ...then call listeners
this._listeners.forEach((listener: ListenerCallback) => listener());
}
subscribe(listener: ListenerCallback): UnsubscribeCallback {
this._listeners.push(listener);
return () => { // returns an "unsubscribe" function
this._listeners = this._listeners.filter(l => l !== listener);
};
}
}
// create a new store
let store = new Store<number>(0);
console.log(store.getState()); // -> 0
// subscribe
let unsubscribe = store.subscribe(() => {
console.log('subscribed: ', store.getState());
});
store.dispatch({ type: 'INCREMENT' }); // -> subscribed: 1
store.dispatch({ type: 'INCREMENT' }); // -> subscribed: 2
unsubscribe();
store.dispatch({ type: 'DECREMENT' }); // (nothing logged)
// decrement happened, even though we weren't listening for it
console.log(store.getState()); // -> 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment