UNPKG

shelving

Version:

Toolkit for using data in JavaScript.

76 lines (75 loc) 2.71 kB
import { UnexpectedError } from "../error/UnexpectedError.js"; import { getGetter } from "../util/class.js"; import { ThroughSequence } from "./ThroughSequence.js"; /** Used when the sequence hasn't inspected anything yet. */ const _NOVALUE = Symbol("shelving/InspectSequence.NOVALUE"); /** * Sequence of values that inspects a source sequence of values as it iterates. * - Stores: first/last yielded value, returned value, whether iteration is done, the number of items that were iterated. * * @example * const watch = new InspectSequence(iterable); * for await (const next of capture) console.log("YIELDED", next); * console.log("FIRST", watch.first); * console.log("RETURNED", watch.returned); */ export class InspectSequence extends ThroughSequence { /** Get the number of results received by this iterator so far. */ count = 0; /** Is the iteration done? */ done = false; /** The first yielded value (throws if the iteration yielded no values, i.e. `this.count === 0`). */ get first() { if (this._first === _NOVALUE) throw new UnexpectedError("Iteration not started", { sequence: this, caller: getGetter(this, "first"), }); return this._first; } _first = _NOVALUE; /** The last yielded value (throws if the iteration yielded no values, i.e. `this.count === 0`). */ get last() { if (this._last === _NOVALUE) throw new UnexpectedError("Iteration not started", { sequence: this, caller: getGetter(this, "last"), }); return this._last; } _last = _NOVALUE; /** The returned value (throws if the iteration is not done, i.e. `this.done === false`). */ get returned() { if (this._returned === _NOVALUE) throw new UnexpectedError("Iteration not done", { sequence: this, caller: getGetter(this, "returned"), }); return this._returned; } _returned = _NOVALUE; // Override to watch returned values. async next() { return this._inspect(await this.next()); } async throw(thrown) { return this._inspect(await this.throw(thrown)); } async return(value) { return this._inspect(await this.return(value)); } /** Capture a result. */ _inspect(result) { if (!result.done) { if (this.first === undefined) this._first = result.value; this._last = result.value; this.count++; } else { this._returned = result.value; this.done = true; } return result; } }