Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RepeatOrNot #70

Open
aravindet opened this issue Apr 3, 2021 · 1 comment
Open

RepeatOrNot #70

aravindet opened this issue Apr 3, 2021 · 1 comment
Labels
enhancement New feature or request

Comments

@aravindet
Copy link

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 read

and

for await (const chunk of read(name)) { ... } // Streaming read

A 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 (name oneTime above) set to true.
  • When .push() is called by the executor, we resolve the stop promise immediately.
  • If the executor throws or calls stop with an argument before pushing a value, reject the promise.
@brainkim brainkim added the enhancement New feature or request label Apr 3, 2021
@brainkim
Copy link
Member

brainkim commented Apr 26, 2021

Sorry for the sluggish response! I hear what you’re saying! I also sometimes wonder about writing simultaneously thenable/async iterable APIs. However, I’m not really sure baking this pattern into the repeater abstraction is the right way to go about things. My guess is, you could probably write your RepeaterOrNot API in user space by composing the repeaters with your own code.

I’m on my phone now, so I’m not really able to write the code that would make this work, but essentially you would create a class which mirrors the Repeater class, construct and retain a repeater instance in the constructor, pass in the modified push and stop functions according to your specification and then implement the then/catch/finally/next/return/throw methods according to your specifications as well?

While I don’t think your proposed API is going to make it in, I encourage to experiment via composition, and if you have any questions or need help, I encourage you to let me know via this issue or by email!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants