@reactivex/ix-esnext-esm
Version:
The Interactive Extensions for JavaScript
58 lines (56 loc) • 2.06 kB
JavaScript
import { AsyncIterableX } from './asynciterablex';
import { identity, identityAsync } from '../util/identity';
// eslint-disable-next-line @typescript-eslint/no-empty-function
const NEVER_PROMISE = new Promise(() => { });
function wrapPromiseWithIndex(promise, index) {
return promise.then(value => ({ value, index }));
}
export class CombineLatestAsyncIterable extends AsyncIterableX {
constructor(sources, fn) {
super();
this._sources = sources;
this._fn = fn;
}
async *[Symbol.asyncIterator]() {
const fn = this._fn;
const length = this._sources.length;
const iterators = new Array(length);
const nexts = new Array(length);
let hasValueAll = false;
const values = new Array(length);
const hasValues = new Array(length);
let active = length;
hasValues.fill(false);
for (let i = 0; i < length; i++) {
const iterator = this._sources[i][Symbol.asyncIterator]();
iterators[i] = iterator;
nexts[i] = wrapPromiseWithIndex(iterator.next(), i);
}
while (active > 0) {
const next = Promise.race(nexts);
const { value: next$, index } = await next;
if (next$.done) {
nexts[index] = NEVER_PROMISE;
active--;
}
else {
values[index] = next$.value;
hasValues[index] = true;
const iterator$ = iterators[index];
nexts[index] = wrapPromiseWithIndex(iterator$.next(), index);
if (hasValueAll || (hasValueAll = hasValues.every(identity))) {
yield await fn(values);
}
}
}
}
}
export function combineLatest(...sources) {
let fn = (sources.shift() || identityAsync);
if (fn && typeof fn !== 'function') {
sources.unshift(fn);
fn = identityAsync;
}
return new CombineLatestAsyncIterable(sources, fn);
}
//# sourceMappingURL=combinelatest.mjs.map