UNPKG

react-async-iterators

Version:

The magic of JavaScript async iterators in React ⛓️ 🧬 🔃

50 lines 2.01 kB
import { promiseWithResolvers } from './promiseWithResolvers.js'; import { callWithArgsOrReturn } from './callWithArgsOrReturn.js'; export { AsyncIterableChannel }; class AsyncIterableChannel { #isClosed = false; #nextIteration = promiseWithResolvers(); #currentValue; constructor(initialValue) { this.#currentValue = initialValue; } put(update) { if (this.#isClosed) { return; } (async () => { this.#currentValue = callWithArgsOrReturn(update, this.#currentValue); await undefined; // Deferring to the next microtick so that an attempt to pull the a value before making multiple rapid synchronous calls to `put()` will make that pull ultimately yield only the last value that was put - instead of the first one as were if this otherwise wasn't deferred. this.#nextIteration.resolve({ done: false, value: this.#currentValue }); this.#nextIteration = promiseWithResolvers(); })(); } close() { this.#isClosed = true; this.#nextIteration.resolve({ done: true, value: undefined }); } out = { value: (() => { const self = this; return { get current() { return self.#currentValue; }, }; })(), [Symbol.asyncIterator]: () => { const whenIteratorClosed = promiseWithResolvers(); return { next: () => { // TODO: Should every iterator of this kind here yield `this.#currentValue` first?... return Promise.race([this.#nextIteration.promise, whenIteratorClosed.promise]); }, return: async () => { whenIteratorClosed.resolve({ done: true, value: undefined }); return { done: true, value: undefined }; }, }; }, }; } //# sourceMappingURL=AsyncIterableChannel.js.map