repeaterjs / repeater

The missing constructor for creating safe async iterators
https://repeater.js.org
MIT License
459 stars 12 forks source link

Question: Convert Observable to Repeater and back #44

Closed vladferix closed 4 years ago

vladferix commented 4 years ago

Hey,

I just wanted to play with repeater, and I was curious whether is it possible for example to convert from Rx.Observable to repeater and back.

Maybe you can point me to some example.

Thanks!

brainkim commented 4 years ago

I haven’t used observables in a while but the following code should work:

function fromObservable(observable) {
  return new Repeater(async (push, stop) => {
    const subscription = observable.subscribe({
      next(value) {
        push(value);
      },
      error(err) {
        stop(err);
      },
      complete() {
        stop();
      },
    });
    await stop;
    subscription.unsubscribe();
  });
}

I haven’t run the code to check for errors but you should get the basic idea. Let me know if this works or you have any other questions! Maybe this could be added to the examples in quickstart if this is helpful.

brainkim commented 4 years ago

As for converting an async iterator to an observable, here’s a rough sketch:

function toObservable(iterator) {
  const subject = new Subject();
  (async function() {
    try {
      for await (const value of iterator) {
        subject.next(value);
        if (subject.isStopped) {
          break;
        }
      }
    } catch (err) {
      subject.error(err);
    } finally {
      subject.complete();
    }
  })();
  return subject;
}

I honestly don’t know which “subject” to use here, you probably know better. Also I’m not 100% sure how to correctly close the async iterator when the subject is unsubscribed.

vladferix commented 4 years ago

Thanks! It would be super helpful to add it as examples. Ideally, I would love to even have some project on npm, to do something like npm install @repeaterjs/repeater-rxjs And just use repeater altogether with my rjx observables. I really see the parallel with Promise here. Sometimes in my code I want to express with creating new Promise() and chaininig it, but sometimes using async/await is much more comfortable for me. And I can always convert it back and forth if I need, so I ideally would like to have the same possibilities with repeater

brainkim commented 4 years ago

Ideally, I would love to even have some project on npm, to do something like npm install @repeaterjs/repeater-rxjs

Maybe. I’m hesitant to write such a package because:

  1. Going from observables to repeaters (fromObservable) is trivial. I haven’t written utility functions for turning other callback-based APIs like mutation observers, event targets or node streams into repeaters because this is the 95% use-case for repeaters: setup callbacks, await stop and teardown callbacks. It’s so easy and straightforward that I’d rather people just do it themselves. Additionally, you may want to patch the [Symbol.asyncIterator] method of observables to make them for…await-able out of the box, without the need for a utility function.

  2. Going from async iterators to observables (toObservable) doesn’t require the repeater class and is much more involved. You can use the async iterator protocol and for…await exclusively to translate async iterators to observables and there is probably no need for repeaters. However, there are additional considerations you need to make which I am unsure of, like which kind of rxjs subject you want to use, whether you want the observable to buffer values, and when to break out of the for…await iterator loop.

I have no objection to people using the “repeater” name however, and I encourage you to create a package called repeater-rxjs if you so desire! This is the nice thing about using a namespaced package scope; I don’t have to be protective about package names in the wild.

As far as actionability of this issue, I think I will definitely add some version of the fromObservable function to the examples, insofar as this will help observable folks map the concept of observables to repeaters.

Again, thanks for the feedback, and I hope you have success with async iterators. If you have any other questions, do not hesitate to reply here or in further issues.

brainkim commented 4 years ago

Observable example added to docs and README