@reactivex/ix-es2015-cjs
Version:
The Interactive Extensions for JavaScript
150 lines (148 loc) • 7.27 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FlattenConcurrentAsyncIterable = void 0;
const tslib_1 = require("tslib");
const asynciterablex_js_1 = require("../asynciterablex.js");
const withabort_js_1 = require("../operators/withabort.js");
const aborterror_js_1 = require("../../aborterror.js");
const safeRace_js_1 = require("../../util/safeRace.js");
const isiterable_js_1 = require("../../util/isiterable.js");
const returniterator_js_1 = require("../../util/returniterator.js");
const NEVER_PROMISE = new Promise(() => { });
function ignoreInnerAbortErrors(signal) {
return function ignoreInnerAbortError(e) {
if (signal.aborted && e instanceof aborterror_js_1.AbortError) {
return NEVER_PROMISE;
}
throw e;
};
}
function wrapIterator(source, index, type, signal) {
return tslib_1.__asyncGenerator(this, arguments, function* wrapIterator_1() {
var _a, e_1, _b, _c;
(0, aborterror_js_1.throwIfAborted)(signal);
try {
for (var _d = true, _e = tslib_1.__asyncValues((0, withabort_js_1.wrapWithAbort)(source, signal)), _f; _f = yield tslib_1.__await(_e.next()), _a = _f.done, !_a; _d = true) {
_c = _f.value;
_d = false;
const value = _c;
(0, aborterror_js_1.throwIfAborted)(signal);
yield yield tslib_1.__await({ type, index, value });
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (!_d && !_a && (_b = _e.return)) yield tslib_1.__await(_b.call(_e));
}
finally { if (e_1) throw e_1.error; }
}
return yield tslib_1.__await({ type, index, value: undefined });
});
}
/** @ignore */
class FlattenConcurrentAsyncIterable extends asynciterablex_js_1.AsyncIterableX {
constructor(_source, _selector, _concurrent, _switchMode, _thisArg) {
super();
this._source = _source;
this._selector = _selector;
this._concurrent = _concurrent;
this._switchMode = _switchMode;
this._thisArg = _thisArg;
this._concurrent = this._switchMode ? 1 : Math.max(_concurrent, 1);
}
[Symbol.asyncIterator](outerSignal) {
return tslib_1.__asyncGenerator(this, arguments, function* _a() {
(0, aborterror_js_1.throwIfAborted)(outerSignal);
let active = 0;
let outerIndex = 0;
let outerComplete = false;
const thisArg = this._thisArg;
const selector = this._selector;
const switchMode = this._switchMode;
const concurrent = this._concurrent;
const outerValues = new Array(0);
const innerIndices = new Array(0);
const controllers = new Array(isFinite(concurrent) ? concurrent : 0);
const inners = new Array(isFinite(concurrent) ? concurrent : 0);
const outer = wrapIterator(this._source, 0, 0 /* Type.OUTER */, outerSignal);
const results = [outer.next()];
try {
do {
const { done = false, value: { type, value, index }, } = yield tslib_1.__await((0, safeRace_js_1.safeRace)(results));
if (!done) {
switch (type) {
case 0 /* Type.OUTER */: {
if (switchMode) {
active = 0;
}
if (active < concurrent) {
pullNextOuter(value);
}
else {
outerValues.push(value);
}
results[0] = outer.next();
break;
}
case 1 /* Type.INNER */: {
yield yield tslib_1.__await(value);
const { [index - 1]: inner } = inners;
const { [index - 1]: { signal }, } = controllers;
results[index] = inner.next().catch(ignoreInnerAbortErrors(signal));
break;
}
}
}
else {
// ignore this result slot
results[index] = NEVER_PROMISE;
switch (type) {
case 0 /* Type.OUTER */: {
outerComplete = true;
break;
}
case 1 /* Type.INNER */: {
--active;
// return the current slot to the pool
innerIndices.push(index);
// synchronously drain the `outerValues` buffer
while (active < concurrent && outerValues.length) {
// Don't use `await` so we avoid blocking while the number of active inner sequences is less than `concurrent`.
pullNextOuter(outerValues.shift());
}
break;
}
}
}
} while (!outerComplete || active + outerValues.length > 0);
}
finally {
controllers.forEach((controller) => controller === null || controller === void 0 ? void 0 : controller.abort());
yield tslib_1.__await(Promise.all([outer, ...inners].map(returniterator_js_1.returnAsyncIterator)));
}
function pullNextOuter(outerValue) {
++active;
const index = innerIndices.pop() || active;
// abort the current inner iterator first
if (switchMode && controllers[index - 1]) {
controllers[index - 1].abort();
}
controllers[index - 1] = new AbortController();
const innerSignal = controllers[index - 1].signal;
// Get the next inner sequence.
// `selector` is a sync or async function that returns AsyncIterableInput.
const inner = selector.call(thisArg, outerValue, outerIndex++, innerSignal);
results[index] = wrapAndPullInner(index, innerSignal, inner).catch(ignoreInnerAbortErrors(innerSignal));
}
function wrapAndPullInner(index, signal, inner) {
if ((0, isiterable_js_1.isPromise)(inner)) {
return inner.then((inner) => wrapAndPullInner(index, signal, inner));
}
return (inners[index - 1] = wrapIterator(asynciterablex_js_1.AsyncIterableX.as(inner), index, 1 /* Type.INNER */, signal)).next();
}
});
}
}
exports.FlattenConcurrentAsyncIterable = FlattenConcurrentAsyncIterable;
//# sourceMappingURL=_flatten.js.map