react-async-iterators
Version:
The magic of JavaScript async iterators in React ⛓️ 🧬 🔃
53 lines • 2.28 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AsyncIterableChannel = void 0;
const promiseWithResolvers_js_1 = require("./promiseWithResolvers.js");
const callWithArgsOrReturn_js_1 = require("./callWithArgsOrReturn.js");
class AsyncIterableChannel {
#isClosed = false;
#nextIteration = (0, promiseWithResolvers_js_1.promiseWithResolvers)();
#currentValue;
constructor(initialValue) {
this.#currentValue = initialValue;
}
put(update) {
if (this.#isClosed) {
return;
}
(async () => {
this.#currentValue = (0, callWithArgsOrReturn_js_1.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 = (0, promiseWithResolvers_js_1.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 = (0, promiseWithResolvers_js_1.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 };
},
};
},
};
}
exports.AsyncIterableChannel = AsyncIterableChannel;
//# sourceMappingURL=AsyncIterableChannel.js.map