Skip to content

Commit

Permalink
refactor(timer): Implement timer as a function
Browse files Browse the repository at this point in the history
- Removes TimerObservable
- Updates tests
  • Loading branch information
benlesh committed Jan 23, 2018
1 parent ab6c325 commit cfd846d
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 133 deletions.
31 changes: 15 additions & 16 deletions spec/observables/timer-spec.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import * as Rx from '../../src/Rx';

import marbleTestingSignature = require('../helpers/marble-testing'); // tslint:disable-line:no-require-imports
import { timer, never } from '../../src/create';
import { TestScheduler } from '../../src/testing';

declare const { asDiagram, time };
declare const asDiagram: any;
declare const time: typeof marbleTestingSignature.time;
declare const expectObservable: typeof marbleTestingSignature.expectObservable;
declare const rxTestScheduler: Rx.TestScheduler;

const Observable = Rx.Observable;
declare const rxTestScheduler: TestScheduler;

/** @test {timer} */
describe('Observable.timer', () => {
describe('timer', () => {
asDiagram('timer(3000, 1000)')('should create an observable emitting periodically', () => {
const e1 = Observable.timer(60, 20, rxTestScheduler)
const e1 = timer(60, 20, rxTestScheduler)
.take(4) // make it actually finite, so it can be rendered
.concat(Observable.never()); // but pretend it's infinite by not completing
.concat(never()); // but pretend it's infinite by not completing
const expected = '------a-b-c-d-';
const values = {
a: 0,
Expand All @@ -28,15 +27,15 @@ describe('Observable.timer', () => {
const dueTime = time('-----|');
const expected = '-----(x|)';

const source = Observable.timer(dueTime, undefined, rxTestScheduler);
const source = timer(dueTime, undefined, rxTestScheduler);
expectObservable(source).toBe(expected, {x: 0});
});

it('should emit a single value immediately', () => {
const dueTime = time('|');
const expected = '(x|)';

const source = Observable.timer(dueTime, rxTestScheduler);
const source = timer(dueTime, rxTestScheduler);
expectObservable(source).toBe(expected, {x: 0});
});

Expand All @@ -45,7 +44,7 @@ describe('Observable.timer', () => {
const period = time( '--|');
const expected = '----a-b-c-d-(e|)';

const source = Observable.timer(dueTime, period, rxTestScheduler).take(5);
const source = timer(dueTime, period, rxTestScheduler).take(5);
const values = { a: 0, b: 1, c: 2, d: 3, e: 4};
expectObservable(source).toBe(expected, values);
});
Expand All @@ -55,7 +54,7 @@ describe('Observable.timer', () => {
const period = time('---|');
const expected = 'a--b--c--d--(e|)';

const source = Observable.timer(dueTime, period, rxTestScheduler).take(5);
const source = timer(dueTime, period, rxTestScheduler).take(5);
const values = { a: 0, b: 1, c: 2, d: 3, e: 4};
expectObservable(source).toBe(expected, values);
});
Expand All @@ -66,7 +65,7 @@ describe('Observable.timer', () => {
const expected = 'a--b--c--d--e';
const unsub = '^ !';

const source = Observable.timer(dueTime, period, rxTestScheduler);
const source = timer(dueTime, period, rxTestScheduler);
const values = { a: 0, b: 1, c: 2, d: 3, e: 4};
expectObservable(source, unsub).toBe(expected, values);
});
Expand All @@ -76,7 +75,7 @@ describe('Observable.timer', () => {
const expected = '----(a|)';

const dueTime = new Date(rxTestScheduler.now() + offset);
const source = Observable.timer(dueTime, null, rxTestScheduler);
const source = timer(dueTime, null, rxTestScheduler);
expectObservable(source).toBe(expected, {a: 0});
});

Expand All @@ -86,7 +85,7 @@ describe('Observable.timer', () => {
const expected = '----a-b-c-d-(e|)';

const dueTime = new Date(rxTestScheduler.now() + offset);
const source = Observable.timer(dueTime, period, rxTestScheduler).take(5);
const source = timer(dueTime, period, rxTestScheduler).take(5);
const values = { a: 0, b: 1, c: 2, d: 3, e: 4};
expectObservable(source).toBe(expected, values);
});
Expand Down
115 changes: 0 additions & 115 deletions src/internal/observable/TimerObservable.ts

This file was deleted.

93 changes: 91 additions & 2 deletions src/internal/observable/timer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,92 @@
import { TimerObservable } from './TimerObservable';
import { Observable } from '../Observable';
import { IScheduler } from '../Scheduler';
import { async } from '../scheduler/async';
import { isNumeric } from '../util/isNumeric';
import { isScheduler } from '../util/isScheduler';
import { Action } from '../scheduler/Action';
import { Subscriber } from '../Subscriber';

export const timer = TimerObservable.create;
/**
* Creates an Observable that starts emitting after an `initialDelay` and
* emits ever increasing numbers after each `period` of time thereafter.
*
* <span class="informal">Its like {@link interval}, but you can specify when
* should the emissions start.</span>
*
* <img src="./img/timer.png" width="100%">
*
* `timer` returns an Observable that emits an infinite sequence of ascending
* integers, with a constant interval of time, `period` of your choosing
* between those emissions. The first emission happens after the specified
* `initialDelay`. The initial delay may be a {@link Date}. By default, this
* operator uses the `async` IScheduler to provide a notion of time, but you
* may pass any IScheduler to it. If `period` is not specified, the output
* Observable emits only one value, `0`. Otherwise, it emits an infinite
* sequence.
*
* @example <caption>Emits ascending numbers, one every second (1000ms), starting after 3 seconds</caption>
* var numbers = Rx.Observable.timer(3000, 1000);
* numbers.subscribe(x => console.log(x));
*
* @example <caption>Emits one number after five seconds</caption>
* var numbers = Rx.Observable.timer(5000);
* numbers.subscribe(x => console.log(x));
*
* @see {@link interval}
* @see {@link delay}
*
* @param {number|Date} [dueTime] The initial delay time to wait before
* emitting the first value of `0`.
* @param {number|IScheduler} [periodOrScheduler] The period of time between emissions of the
* subsequent numbers.
* @param {IScheduler} [scheduler=async] The IScheduler to use for scheduling
* the emission of values, and providing a notion of "time".
* @return {Observable} An Observable that emits a `0` after the
* `initialDelay` and ever increasing numbers after each `period` of time
* thereafter.
* @static true
* @name timer
* @owner Observable
*/
export function timer(dueTime: number | Date = 0,
periodOrScheduler?: number | IScheduler,
scheduler?: IScheduler): Observable<number> {
let period = -1;
if (isNumeric(periodOrScheduler)) {
period = Number(periodOrScheduler) < 1 && 1 || Number(periodOrScheduler);
} else if (isScheduler(periodOrScheduler)) {
scheduler = periodOrScheduler as any;
}

if (!isScheduler(scheduler)) {
scheduler = async;
}

const due = isNumeric(dueTime)
? (dueTime as number)
: (+dueTime - scheduler.now());

return new Observable(subscriber => scheduler.schedule(dispatch, due, {
index: 0, period, subscriber
}));
}

interface TimerState {
index: number;
period: number;
subscriber: Subscriber<number>;
}

function dispatch(this: Action<TimerState>, state: TimerState) {
const { index, period, subscriber } = state;
subscriber.next(index);

if (subscriber.closed) {
return;
} else if (period === -1) {
return subscriber.complete();
}

state.index = index + 1;
this.schedule(state, period);
}

0 comments on commit cfd846d

Please sign in to comment.