Skip to content

Instantly share code, notes, and snippets.

@Sawtaytoes
Last active February 27, 2020 11:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sawtaytoes/7b6bf968510fe88df3ec98846a641779 to your computer and use it in GitHub Desktop.
Save Sawtaytoes/7b6bf968510fe88df3ec98846a641779 to your computer and use it in GitHub Desktop.
`createIteratorSubject` allows someone to create an observable out of a generator and tell RxJS when to pull the next value instead of relying on the official implementation which creates backpressure.
const { BehaviorSubject, Subject } = require('rxjs')
const { map, tap, withLatestFrom } = require('rxjs/operators')
const createIteratorSubject = (
iterator,
) => {
const iterator$ = (
new BehaviorSubject()
)
const pushNextValue = ({
done,
value,
}) => {
done
&& value === undefined
? (
iterator$
.complete()
)
: (
iterator$
.next(value)
)
}
iterator$
.push = (
value,
) => (
pushNextValue(
iterator
.next(value)
)
)
iterator$
.push()
return iterator$
}
module.exports = createIteratorSubject
@omatrot
Copy link

omatrot commented Mar 2, 2019

Hi, I've gone through your blog post that led me here.
Your approach to backpressure is probably what I need in my use case:
I have the following typescript code where I would like to add backpressure control:

private emitter!: Observable<any>;
private rxSubscription!: RxSubscription;

// Connect the bluetooth event to an RxJS emitter
this.emitter = fromEventPattern(this.addHandler, this.removeHandler, (err, char) => [err, char]);

// save all incoming data to disk (unfiltered)
this.rxSubscription = this.emitter.subscribe(this.handleUpdateValueForDiskStorage);

What would be the proper way to use your approach in my code?
How to turn my observable to an iterator to call createIteratorSubject on it?

The second challenge is that I have a child subscription.
Should I call push on the iterator in the child subscription, on in the parent subscription?

Thanks in advance.

@Seairth
Copy link

Seairth commented Aug 19, 2019

I found the above snippet difficult to read. Consider using a different name for subject, as well as a more compact format overall. For example:

const { BehaviorSubject } = require('rxjs')

function createIteratorSubject(iterator) {
  const subject$ = new BehaviorSubject();

  subject$.push = function(value) {
    const {done, value} = iterator.next(value);.

    if (done && value === undefined) {
        subject$.complete();
    } else {
        subject$.next(value);
    } 
  }

  subject$.push()

  return subject$
}

module.exports = createIteratorSubject

@anilanar
Copy link

What an interesting code format, do you have an auto formatter for that?

@Sawtaytoes
Copy link
Author

@anilanar I'd love to have an auto-formatter and will be looking into using ESLint rules to achieve it (if that's even possible).

Unlike Prettier, there are a set of rules I follow so it's easy for someone else to replicate and get the same results. At my last job, you'd be unable to tell my code apart from my coworkers'. In fact, there was one bug we ended up fixing in separate PRs with the exact same solution line-by-line.

@Sawtaytoes
Copy link
Author

@anilanar I now have an eslint extension available.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment