import { Observable } from '../Observable'; import { async } from '../scheduler/async'; import { SchedulerLike, OperatorFunction } from '../types'; import { scan } from './scan'; import { defer } from '../observable/defer'; import { map } from './map'; /** * * Emits an object containing the current value, and the time that has * passed between emitting the current value and the previous value, which is * calculated by using the provided `scheduler`'s `now()` method to retrieve * the current time at each emission, then calculating the difference. The `scheduler` * defaults to {@link asyncScheduler}, so by default, the `interval` will be in * milliseconds. * * Convert an Observable that emits items into one that * emits indications of the amount of time elapsed between those emissions. * * ![](timeinterval.png) * * ## Examples * Emit inteval between current value with the last value * * ```ts * const seconds = interval(1000); * * seconds.pipe(timeInterval()) * .subscribe( * value => console.log(value), * err => console.log(err), * ); * * seconds.pipe(timeout(900)) * .subscribe( * value => console.log(value), * err => console.log(err), * ); * * // NOTE: The values will never be this precise, * // intervals created with `interval` or `setInterval` * // are non-deterministic. * * // {value: 0, interval: 1000} * // {value: 1, interval: 1000} * // {value: 2, interval: 1000} * ``` * * @param {SchedulerLike} [scheduler] Scheduler used to get the current time. * @return {Observable<{ interval: number, value: T }>} Observable that emit infomation about value and interval * @method timeInterval */ export function timeInterval(scheduler: SchedulerLike = async): OperatorFunction> { return (source: Observable) => defer(() => { return source.pipe( // TODO(benlesh): correct these typings. scan( ({ current }, value) => ({ value, current: scheduler.now(), last: current }), { current: scheduler.now(), value: undefined, last: undefined } ) as any, map>(({ current, last, value }) => new TimeInterval(value, current - last)), ); }); } // TODO(benlesh): make this an interface, export the interface, but not the implemented class, // there's no reason users should be manually creating this type. /** * @deprecated exposed API, use as interface only. */ export class TimeInterval { constructor(public value: T, public interval: number) {} }