From f7ff7ec72d4d2ab342c669b9532036685a0c4cf2 Mon Sep 17 00:00:00 2001 From: Paul Taylor Date: Fri, 12 Feb 2016 18:11:36 -0800 Subject: [PATCH] feat(if): add static Observable.if creation operator. --- package.json | 2 +- spec/observables/if-spec.ts | 28 +++++++++++++++++++++++ src/Observable.ts | 6 +++-- src/Rx.KitchenSink.ts | 1 + src/add/observable/if.ts | 4 ++++ src/observable/IfObservable.ts | 42 ++++++++++++++++++++++++++++++++++ 6 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 spec/observables/if-spec.ts create mode 100644 src/add/observable/if.ts create mode 100644 src/observable/IfObservable.ts diff --git a/package.json b/package.json index 905de3b49b..a31d0a2486 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "commit": "git-cz", "compile_dist_amd": "tsc ./typings/main.d.ts ./dist/amd/src/Rx.ts ./dist/amd/src/Rx.KitchenSink.ts ./dist/amd/src/Rx.DOM.ts ./dist/amd/src/add/observable/of.ts -m amd --sourceMap --outDir ./dist/amd --target ES5 --diagnostics --pretty --noImplicitAny --suppressImplicitAnyIndexErrors", "compile_dist_cjs": "tsc ./typings/main.d.ts ./dist/cjs/src/Rx.ts ./dist/cjs/src/Rx.KitchenSink.ts ./dist/cjs/src/Rx.DOM.ts ./dist/cjs/src/add/observable/of.ts -m commonjs --sourceMap --outDir ./dist/cjs --target ES5 -d --diagnostics --pretty --noImplicitAny --suppressImplicitAnyIndexErrors", - "compile_dist_es6": "tsc ./dist/es6/src/Rx.ts ./dist/es6/src/Rx.KitchenSink.ts ./dist/es6/src/Rx.DOM.ts ./dist/es6/src/add/observable/of.ts -m es2015 --sourceMap --outDir ./dist/es6 --target ES6 -d --diagnostics --pretty --noImplicitAny --suppressImplicitAnyIndexErrors", + "compile_dist_es6": "tsc ./dist/es6/src/Rx.ts ./dist/es6/src/Rx.KitchenSink.ts ./dist/es6/src/Rx.DOM.ts ./dist/es6/src/add/observable/of.ts -m es2015 --sourceMap --outDir ./dist/es6 --target ES6 -d --diagnostics --pretty --noImplicitAny --suppressImplicitAnyIndexErrors", "cover": "npm run cover_test && npm run cover_remapping", "cover_test": "istanbul cover -x \"*-spec.js index.js *-helper.js spec-js/helpers/*\" ./node_modules/jasmine/bin/jasmine.js", "cover_remapping": "remap-istanbul -i coverage/coverage.json -o coverage/coverage-remapped.json && remap-istanbul -i coverage/coverage.json -o coverage/coverage-remapped.lcov -t lcovonly && remap-istanbul -i coverage/coverage.json -o coverage/coverage-remapped -t html", diff --git a/spec/observables/if-spec.ts b/spec/observables/if-spec.ts new file mode 100644 index 0000000000..b0e9ef58d4 --- /dev/null +++ b/spec/observables/if-spec.ts @@ -0,0 +1,28 @@ +import * as Rx from '../../dist/cjs/Rx.KitchenSink'; +import {expectObservable} from '../helpers/marble-testing'; +import {it} from '../helpers/test-helper'; + +const Observable = Rx.Observable; + +describe('Observable.if', () => { + it('should subscribe to thenSource when the conditional returns true', () => { + const e1 = Observable.if(() => true, Observable.of('a')); + const expected = '(a|)'; + + expectObservable(e1).toBe(expected); + }); + + it('should subscribe to elseSource when the conditional returns false', () => { + const e1 = Observable.if(() => false, Observable.of('a'), Observable.of('b')); + const expected = '(b|)'; + + expectObservable(e1).toBe(expected); + }); + + it('should complete without an elseSource when the conditional returns false', () => { + const e1 = Observable.if(() => false, Observable.of('a')); + const expected = '|'; + + expectObservable(e1).toBe(expected); + }); +}); diff --git a/src/Observable.ts b/src/Observable.ts index 255152626b..8de30e816c 100644 --- a/src/Observable.ts +++ b/src/Observable.ts @@ -6,6 +6,7 @@ import {root} from './util/root'; import {SymbolShim} from './util/SymbolShim'; import {toSubscriber} from './util/toSubscriber'; +import {IfObservable} from './observable/IfObservable'; import {ErrorObservable} from './observable/ErrorObservable'; export type ObservableOrPromise = Observable | Promise; @@ -150,7 +151,8 @@ export class Observable { return this.source.subscribe(subscriber); } - // Throw is the special snow flake, the compiler sees it as a reserved word + // `if` and `throw` are special snow flakes, the compiler sees them as reserved words + static if: typeof IfObservable.create; static throw: typeof ErrorObservable.create; /** @@ -161,4 +163,4 @@ export class Observable { [SymbolShim.observable]() { return this; } -} \ No newline at end of file +} diff --git a/src/Rx.KitchenSink.ts b/src/Rx.KitchenSink.ts index 6202311f59..3f7a8c0634 100644 --- a/src/Rx.KitchenSink.ts +++ b/src/Rx.KitchenSink.ts @@ -1,6 +1,7 @@ export * from './Rx'; // statics +import './add/observable/if'; import './add/observable/using'; // Operators diff --git a/src/add/observable/if.ts b/src/add/observable/if.ts new file mode 100644 index 0000000000..e2d9a04546 --- /dev/null +++ b/src/add/observable/if.ts @@ -0,0 +1,4 @@ +import {Observable} from '../../Observable'; +import {IfObservable} from '../../observable/IfObservable'; + +Observable.if = IfObservable.create; diff --git a/src/observable/IfObservable.ts b/src/observable/IfObservable.ts new file mode 100644 index 0000000000..c12ba85be1 --- /dev/null +++ b/src/observable/IfObservable.ts @@ -0,0 +1,42 @@ +import {Observable} from '../Observable'; +import {Subscriber} from '../Subscriber'; +import {Subscription} from '../Subscription'; + +export class IfObservable extends Observable { + + static create(condition: () => boolean, + thenSource?: Observable, + elseSource?: Observable): Observable { + return new IfObservable(condition, thenSource, elseSource); + } + + constructor(private condition: () => boolean, + private thenSource?: Observable, + private elseSource?: Observable) { + super(); + } + + protected _subscribe(subscriber: Subscriber): Subscription | Function | void { + + const { condition, thenSource, elseSource } = this; + + let result: boolean, error: any, errorHappened = false; + + try { + result = condition(); + } catch (e) { + error = e; + errorHappened = true; + } + + if (errorHappened) { + subscriber.error(error); + } else if (result && thenSource) { + return thenSource.subscribe(subscriber); + } else if (elseSource) { + return elseSource.subscribe(subscriber); + } else { + subscriber.complete(); + } + } +}