import { OpenPromise } from "./OpenPromise.js"; //const test = Symbol("test"); /** * A subscription is a promise that gets reresolved multiple times. * * Subscriptions implments the asynchronous iterable protocol (@see AsyncIterable). * This makes it easy to iterate on subscriptions. * * @example ``` * async function demo() { * let subscription = new Subscription(); * * global.setTimeout(() => { * subscription.setCurrent(new Date().toString()); * }, 1000) * * for await (let item of subscription) { * console.log(item, "Subscription has new data") * } * } * ``` */ export class Subscription implements AsyncIterable { public _current: T | undefined = undefined; public pending: OpenPromise = new OpenPromise(); [Symbol.asyncIterator](): AsyncIterator { return new SubscribedResourceIterator(this); } get current(): Promise { if (this._current) { return Promise.resolve(this._current); } return this.pending; } setCurrent(value: T) { this._current = value; //console.warn("RESOLVING WITH", value); this.pending.resolve(value); this.pending = new OpenPromise(); } } export class SubscribedResourceIterator implements AsyncIterator { hasDeliveredFirst = false; constructor(public source: Subscription) { } next(): Promise> { let prom: Promise>; if (!this.hasDeliveredFirst && this.source._current !== undefined) { this.hasDeliveredFirst = true; //console.log("DELIVERING LAST KNOWN VALUE", this.source._current); prom = Promise.resolve({ done: false, value: this.source._current }) } else { this.hasDeliveredFirst = true; prom = new Promise(async (resolve, reject) => { this.source.pending.then((value: T) => { // if (value == null) { // console.error(`why is this`) // } //console.log("DELIVERING AWAITED VALUE ", value); resolve({ done: false, value: value as T }); }); }); } return prom; } }