UNPKG

@johngw/stream

Version:

Reactive programming tools using the WHATWG Streams API.

118 lines 2.81 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CachableSource = void 0; const Async_1 = require("@johngw/stream-common/Async"); /** * The source of a `ReadableStream` that queues items * only when a timed cache becomes invalid. * * @group Sources * @see {@link StorageCache} * @see {@link CachableStream:class} * @example * Caching for 30 minutes. * * ``` * const cache = new StorageCache( * localStorage, * 'my-cache', * 30 * 60_000 * ) * * let i = 0 * const stream = new ReadableStream( * new CachableSource<number>( * cache, * ['numbers'], * () => ++i * ) * ) * * stream.pipeTo(write(console.info)) * // 1 * * await setTimeout(30 * 60_000)) * // 2 * ``` * @example * Manually clearing cache. * * ``` * const cache = new StorageCache( * localStorage, * 'my-cache', * 30 * 60_000 * ) * * let i = 0 * const source = new CachableSource<number>( * cache, * ['numbers'], * () => ++i * ) * * const stream = new ReadableStream(source) * * stream.pipeTo(write(console.info)) * // 1 * * source.clear() * // 2 * ``` */ class CachableSource { #abortController = new AbortController(); #sourceHasFinished = false; #cache; #ms; #path; #pullResult; constructor(cache, path, pullResult, ms = cache.ms) { this.#cache = cache; this.#ms = ms; this.#path = path; this.#pullResult = pullResult; } async pull(controller) { if (this.#sourceHasFinished) { const item = this.#cache.get(this.#path); return item === undefined ? controller.close() : controller.enqueue(item); } else if (await this.#cache.updateIfStale(this.#path, this.#pullItem, this.#ms)) controller.enqueue(this.#cache.get(this.#path)); else await this.#wait(this.#cache.timeLeft(this.#path)); if (controller.desiredSize) return this.pull(controller); } cancel(reason) { this.#abortController.abort(reason); } #pullItem = async () => { const result = await this.#pullResult(); if (result.done) this.#sourceHasFinished = true; else return result.value; }; async #wait(ms) { try { await (0, Async_1.timeout)(ms, undefined, this.#abortController.signal); } catch (error) { // } } clear() { this.#cache.unset(this.#path); this.#abortController.abort('clear'); this.#abortController = new AbortController(); } get sourceHasFinished() { return this.#sourceHasFinished; } } exports.CachableSource = CachableSource; //# sourceMappingURL=CachableSource.js.map