UNPKG

@reactivex/ix-es2015-cjs

Version:

The Interactive Extensions for JavaScript

150 lines (148 loc) 7.27 kB
"use strict"; 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