pnpm
Version:
Fast, disk space efficient package manager
114 lines (94 loc) • 3.09 kB
JavaScript
/** @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)
}
}