-
Notifications
You must be signed in to change notification settings - Fork 15
Description
This is an idea for a new feature, either in Repeater or as a separate class in the same project.
The idea: The object returned by new Repeater() should have an additional .then method, which will be a one-time-use variant of .next.
Background: Repeater combinators, Crank JS components etc. can cleverly accept Promises in place of Async Iterables. I would like to write a library that does the reverse of this: provide values that other peoples’ code can use as either a Promise or an Async Iterable.
Example: Say I want to implement a file read() function which can be used in two ways:
const result = await read(name); // Buffered readand
for await (const chunk of read(name)) { ... } // Streaming readA good API to help me write this function might be:
function read(filename) {
return new RepeatOrNot(async (push, stop) => {
const emitter = getDataEventEmitter(filename);
const buffer = [];
emitter.on('data', (chunk) => {
if (stop.oneTime) buffer.push(chunk);
else push(chunk);
});
emitter.on('close', () => {
if (stop.oneTime) push(buffer.join(''));
else stop();
}
await stop();
emitter.closeAndCleanUp();
});
}This could be implemented with the following additional behavior on top of Repeater:
When .then() is called on the returned object:
- we remove [Symbol.asyncIterator], .next, .return etc. from the object. We would do the same to .then if .next were called first.
- the executor is invoked, with an additional property on
stop(nameoneTimeabove) set to true. - When .push() is called by the executor, we resolve the
stoppromise immediately. - If the executor throws or calls stop with an argument before pushing a value, reject the promise.