UNPKG

pnpm

Version:

Fast, disk space efficient package manager

114 lines (94 loc) 3.09 kB
/** @license MIT License (c) copyright 2010-2016 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ import Stream from '../Stream' import * as transform from './transform' import * as core from '../source/core' import Pipe from '../sink/Pipe' import IndexSink from '../sink/IndexSink' import * as dispose from '../disposable/dispose' import * as base from '@most/prelude' import invoke from '../invoke' var map = base.map var tail = base.tail /** * Combine latest events from all input streams * @param {function(...events):*} f function to combine most recent events * @returns {Stream} stream containing the result of applying f to the most recent * event of each input stream, whenever a new event arrives on any stream. */ export function combine (f /*, ...streams */) { return combineArray(f, tail(arguments)) } /** * Combine latest events from all input streams * @param {function(...events):*} f function to combine most recent events * @param {[Stream]} streams most recent events * @returns {Stream} stream containing the result of applying f to the most recent * event of each input stream, whenever a new event arrives on any stream. */ export function combineArray (f, streams) { var l = streams.length return l === 0 ? core.empty() : l === 1 ? transform.map(f, streams[0]) : new Stream(combineSources(f, streams)) } function combineSources (f, streams) { return new Combine(f, map(getSource, streams)) } function getSource (stream) { return stream.source } function Combine (f, sources) { this.f = f this.sources = sources } Combine.prototype.run = function (sink, scheduler) { var l = this.sources.length var disposables = new Array(l) var sinks = new Array(l) var mergeSink = new CombineSink(disposables, sinks, sink, this.f) for (var indexSink, i = 0; i < l; ++i) { indexSink = sinks[i] = new IndexSink(i, mergeSink) disposables[i] = this.sources[i].run(indexSink, scheduler) } return dispose.all(disposables) } function CombineSink (disposables, sinks, sink, f) { this.sink = sink this.disposables = disposables this.sinks = sinks this.f = f var l = sinks.length this.awaiting = l this.values = new Array(l) this.hasValue = new Array(l) for (var i = 0; i < l; ++i) { this.hasValue[i] = false } this.activeCount = sinks.length } CombineSink.prototype.error = Pipe.prototype.error CombineSink.prototype.event = function (t, indexedValue) { var i = indexedValue.index var awaiting = this._updateReady(i) this.values[i] = indexedValue.value if (awaiting === 0) { this.sink.event(t, invoke(this.f, this.values)) } } CombineSink.prototype._updateReady = function (index) { if (this.awaiting > 0) { if (!this.hasValue[index]) { this.hasValue[index] = true this.awaiting -= 1 } } return this.awaiting } CombineSink.prototype.end = function (t, indexedValue) { dispose.tryDispose(t, this.disposables[indexedValue.index], this.sink) if (--this.activeCount === 0) { this.sink.end(t, indexedValue.value) } }