Skip to content

Commit

Permalink
feat(toggle): Add a toggle factory.
Browse files Browse the repository at this point in the history
  • Loading branch information
cartant committed Jul 16, 2018
1 parent cdc5d25 commit 3cb7e4f
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 0 deletions.
1 change: 1 addition & 0 deletions source/observable/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export * from "./mergeArray";
export * from "./NotificationQueue";
export * from "./queue";
export * from "./separate";
export * from "./toggle";
export * from "./traverse";
export * from "./zipArray";
export * from "./zipPadded";
90 changes: 90 additions & 0 deletions source/observable/toggle-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
* @license Use of this source code is governed by an MIT-style license that
* can be found in the LICENSE file at https://github.com/cartant/rxjs-etc
*/
/*tslint:disable:no-unused-expression*/

import { bufferToggle, concatAll, switchMap, takeUntil, windowToggle } from "rxjs/operators";
import { marbles } from "rxjs-marbles";
import { toggle } from "./toggle";

describe("toggle", () => {

it("should play nice with switchMap", marbles(m => {

const source = m.hot("ab-cd-ef-gh");
const sourceSubs = [
"--^--!-----",
"--------^--"
];
const notifier = m.hot("--x--x--x--");
const expected = "---cd----gh";

const [on, off] = toggle(notifier);
const destination = on.pipe(
switchMap(() => source.pipe(takeUntil(off)))
);
m.expect(destination).toBeObservable(expected);
m.expect(source).toHaveSubscriptions(sourceSubs);
}));

it("should play nice with bufferToggle", marbles(m => {

const source = m.hot("ab-cd-ef-gh");
const sourceSubs = "^----------";
const notifier = m.hot("--x--x--x--");
const expected = "-----(cd)--";

const [on, off] = toggle(notifier);
const destination = source.pipe(
bufferToggle(on, () => off),
concatAll()
);
m.expect(destination).toBeObservable(expected);
m.expect(source).toHaveSubscriptions(sourceSubs);
}));

it("should play nice with windowToggle", marbles(m => {

const source = m.hot("ab-cd-ef-gh");
const sourceSubs = "^----------";
const notifier = m.hot("--x--x--x--");
const expected = "---cd----gh";

const [on, off] = toggle(notifier);
const destination = source.pipe(
windowToggle(on, () => off),
concatAll()
);
m.expect(destination).toBeObservable(expected);
m.expect(source).toHaveSubscriptions(sourceSubs);
}));

it("should support three states", marbles(m => {

const notifier = m.hot("abcdef");
const e1 = "a--d--";
const e2 = "-b--e-";
const e3 = "--c--f";

const [t1, t2, t3] = toggle(notifier, 3);
m.expect(t1).toBeObservable(e1);
m.expect(t2).toBeObservable(e2);
m.expect(t3).toBeObservable(e3);
}));

it("should support four states", marbles(m => {

const notifier = m.hot("abcdef");
const e1 = "a---e-";
const e2 = "-b---f";
const e3 = "--c---";
const e4 = "---d--";

const [t1, t2, t3, t4] = toggle(notifier, 4);
m.expect(t1).toBeObservable(e1);
m.expect(t2).toBeObservable(e2);
m.expect(t3).toBeObservable(e3);
m.expect(t4).toBeObservable(e4);
}));
});
26 changes: 26 additions & 0 deletions source/observable/toggle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* @license Use of this source code is governed by an MIT-style license that
* can be found in the LICENSE file at https://github.com/cartant/rxjs-etc
*/

import { Observable } from "rxjs";
import { filter, map, share } from "rxjs/operators";

export function toggle<T>(source: Observable<T>): [Observable<T>, Observable<T>];
export function toggle<T>(source: Observable<T>, states: 2): [Observable<T>, Observable<T>];
export function toggle<T>(source: Observable<T>, states: 3): [Observable<T>, Observable<T>, Observable<T>];
export function toggle<T>(source: Observable<T>, states: number): Observable<T>[];
export function toggle<T>(source: Observable<T>, states: number = 2): Observable<T>[] {
const result: Observable<T>[] = [];
const indexed = source.pipe(
map((value, index) => [index, value] as [number, T]),
share()
);
for (let state = 0; state < states; ++state) {
result.push(indexed.pipe(
filter(([index]) => (index % states) === state),
map(([, value]) => value)
));
}
return result;
}

0 comments on commit 3cb7e4f

Please sign in to comment.