Skip to content

Commit

Permalink
refactor(defer): make defer creation just a function (#3240)
Browse files Browse the repository at this point in the history
- Removes DeferObservable
- Updates tests
  • Loading branch information
benlesh authored Jan 26, 2018
1 parent 6a4ace4 commit 99b4937
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 110 deletions.
27 changes: 13 additions & 14 deletions spec/observables/defer-spec.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import { expect } from 'chai';
import * as Rx from '../../src/Rx';
import marbleTestingSignature = require('../helpers/marble-testing'); // tslint:disable-line:no-require-imports
import { defer } from '../../src/create';
import { Observable } from '../../src';

declare const { asDiagram };
declare const asDiagram: any;
declare const hot: typeof marbleTestingSignature.hot;
declare const cold: typeof marbleTestingSignature.cold;
declare const expectObservable: typeof marbleTestingSignature.expectObservable;
declare const expectSubscriptions: typeof marbleTestingSignature.expectSubscriptions;

const Observable = Rx.Observable;

/** @test {defer} */
describe('Observable.defer', () => {
describe('defer', () => {
asDiagram('defer(() => Observable.of(a, b, c))')
('should defer the creation of a simple Observable', () => {
const expected = '-a--b--c--|';
const e1 = Observable.defer(() => cold('-a--b--c--|'));
const e1 = defer(() => cold('-a--b--c--|'));
expectObservable(e1).toBe(expected);
});

Expand All @@ -24,7 +23,7 @@ describe('Observable.defer', () => {
const sourceSubs = '^ !';
const expected = '--a--b--c--|';

const e1 = Observable.defer(() => source);
const e1 = defer(() => source);

expectObservable(e1).toBe(expected);
expectSubscriptions(source.subscriptions).toBe(sourceSubs);
Expand All @@ -35,15 +34,15 @@ describe('Observable.defer', () => {
const sourceSubs = '(^!)';
const expected = '|';

const e1 = Observable.defer(() => source);
const e1 = defer(() => source);

expectObservable(e1).toBe(expected);
expectSubscriptions(source.subscriptions).toBe(sourceSubs);
});

it('should accept factory returns promise resolves', (done: MochaDone) => {
const expected = 42;
const e1 = Observable.defer(() => {
const e1 = defer(() => {
return new Promise((resolve: any) => { resolve(expected); });
});

Expand All @@ -57,7 +56,7 @@ describe('Observable.defer', () => {

it('should accept factory returns promise rejects', (done: MochaDone) => {
const expected = 42;
const e1 = Observable.defer(() => {
const e1 = defer(() => {
return new Promise((resolve: any, reject: any) => { reject(expected); });
});

Expand All @@ -76,14 +75,14 @@ describe('Observable.defer', () => {
const sourceSubs = '(^!)';
const expected = '#';

const e1 = Observable.defer(() => source);
const e1 = defer(() => source);

expectObservable(e1).toBe(expected);
expectSubscriptions(source.subscriptions).toBe(sourceSubs);
});

it('should create an observable when factory throws', () => {
const e1 = Observable.defer(() => {
const e1 = defer(() => {
throw 'error';
});
const expected = '#';
Expand All @@ -97,7 +96,7 @@ describe('Observable.defer', () => {
const expected = '--a--b- ';
const unsub = ' ! ';

const e1 = Observable.defer(() => source);
const e1 = defer(() => source);

expectObservable(e1, unsub).toBe(expected);
expectSubscriptions(source.subscriptions).toBe(sourceSubs);
Expand All @@ -109,7 +108,7 @@ describe('Observable.defer', () => {
const expected = '--a--b- ';
const unsub = ' ! ';

const e1 = Observable.defer(() => source.mergeMap((x: string) => Observable.of(x)))
const e1 = defer(() => source.mergeMap((x: string) => Observable.of(x)))
.mergeMap((x: string) => Observable.of(x));

expectObservable(e1, unsub).toBe(expected);
Expand Down
94 changes: 0 additions & 94 deletions src/internal/observable/DeferObservable.ts

This file was deleted.

64 changes: 62 additions & 2 deletions src/internal/observable/defer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,63 @@
import { DeferObservable } from './DeferObservable';
import { Observable, SubscribableOrPromise } from '../Observable';
import { from } from './from'; // lol
import { empty } from './empty';

export const defer = DeferObservable.create;
/**
* Creates an Observable that, on subscribe, calls an Observable factory to
* make an Observable for each new Observer.
*
* <span class="informal">Creates the Observable lazily, that is, only when it
* is subscribed.
* </span>
*
* <img src="./img/defer.png" width="100%">
*
* `defer` allows you to create the Observable only when the Observer
* subscribes, and create a fresh Observable for each Observer. It waits until
* an Observer subscribes to it, and then it generates an Observable,
* typically with an Observable factory function. It does this afresh for each
* subscriber, so although each subscriber may think it is subscribing to the
* same Observable, in fact each subscriber gets its own individual
* Observable.
*
* @example <caption>Subscribe to either an Observable of clicks or an Observable of interval, at random</caption>
* var clicksOrInterval = Rx.Observable.defer(function () {
* if (Math.random() > 0.5) {
* return Rx.Observable.fromEvent(document, 'click');
* } else {
* return Rx.Observable.interval(1000);
* }
* });
* clicksOrInterval.subscribe(x => console.log(x));
*
* // Results in the following behavior:
* // If the result of Math.random() is greater than 0.5 it will listen
* // for clicks anywhere on the "document"; when document is clicked it
* // will log a MouseEvent object to the console. If the result is less
* // than 0.5 it will emit ascending numbers, one every second(1000ms).
*
* @see {@link create}
*
* @param {function(): SubscribableOrPromise} observableFactory The Observable
* factory function to invoke for each Observer that subscribes to the output
* Observable. May also return a Promise, which will be converted on the fly
* to an Observable.
* @return {Observable} An Observable whose Observers' subscriptions trigger
* an invocation of the given Observable factory function.
* @static true
* @name defer
* @owner Observable
*/
export function defer<T>(observableFactory: () => SubscribableOrPromise<T> | void): Observable<T> {
return new Observable(subscriber => {
let input: SubscribableOrPromise<T> | void;
try {
input = observableFactory();
} catch (err) {
subscriber.error(err);
return undefined;
}
const source = input ? from(input) : empty();
return source.subscribe(subscriber);
});
}

0 comments on commit 99b4937

Please sign in to comment.