pnpm
Version:
Fast, disk space efficient package manager
140 lines (114 loc) • 3.39 kB
JavaScript
/** @license MIT License (c) copyright 2010-2016 original author or authors */
/** @author Brian Cavalier */
/** @author John Hann */
import Stream from '../Stream'
import Pipe from '../sink/Pipe'
import Map from '../fusion/Map'
/**
* Limit the rate of events by suppressing events that occur too often
* @param {Number} period time to suppress events
* @param {Stream} stream
* @returns {Stream}
*/
export function throttle (period, stream) {
return new Stream(throttleSource(period, stream.source))
}
function throttleSource (period, source) {
return source instanceof Map ? commuteMapThrottle(period, source)
: source instanceof Throttle ? fuseThrottle(period, source)
: new Throttle(period, source)
}
function commuteMapThrottle (period, source) {
return Map.create(source.f, throttleSource(period, source.source))
}
function fuseThrottle (period, source) {
return new Throttle(Math.max(period, source.period), source.source)
}
function Throttle (period, source) {
this.period = period
this.source = source
}
Throttle.prototype.run = function (sink, scheduler) {
return this.source.run(new ThrottleSink(this.period, sink), scheduler)
}
function ThrottleSink (period, sink) {
this.time = 0
this.period = period
this.sink = sink
}
ThrottleSink.prototype.event = function (t, x) {
if (t >= this.time) {
this.time = t + this.period
this.sink.event(t, x)
}
}
ThrottleSink.prototype.end = Pipe.prototype.end
ThrottleSink.prototype.error = Pipe.prototype.error
/**
* Wait for a burst of events to subside and emit only the last event in the burst
* @param {Number} period events occuring more frequently than this
* will be suppressed
* @param {Stream} stream stream to debounce
* @returns {Stream} new debounced stream
*/
export function debounce (period, stream) {
return new Stream(new Debounce(period, stream.source))
}
function Debounce (dt, source) {
this.dt = dt
this.source = source
}
Debounce.prototype.run = function (sink, scheduler) {
return new DebounceSink(this.dt, this.source, sink, scheduler)
}
function DebounceSink (dt, source, sink, scheduler) {
this.dt = dt
this.sink = sink
this.scheduler = scheduler
this.value = void 0
this.timer = null
this.disposable = source.run(this, scheduler)
}
DebounceSink.prototype.event = function (t, x) {
this._clearTimer()
this.value = x
this.timer = this.scheduler.delay(this.dt, new DebounceTask(this, x))
}
DebounceSink.prototype._event = function (t, x) {
this._clearTimer()
this.sink.event(t, x)
}
DebounceSink.prototype.end = function (t, x) {
if (this._clearTimer()) {
this.sink.event(t, this.value)
this.value = void 0
}
this.sink.end(t, x)
}
DebounceSink.prototype.error = function (t, x) {
this._clearTimer()
this.sink.error(t, x)
}
DebounceSink.prototype.dispose = function () {
this._clearTimer()
return this.disposable.dispose()
}
DebounceSink.prototype._clearTimer = function () {
if (this.timer === null) {
return false
}
this.timer.dispose()
this.timer = null
return true
}
function DebounceTask (debounce, value) {
this.debounce = debounce
this.value = value
}
DebounceTask.prototype.run = function (t) {
this.debounce._event(t, this.value)
}
DebounceTask.prototype.error = function (t, e) {
this.debounce.error(t, e)
}
DebounceTask.prototype.dispose = function () {}