U Avalos
U Avalos

Reputation: 6798

Ignore events on stream until condition is satisfied?

I created a stream from button click events. The button corresponds to a create action on the database. Obviously, I want the database action to fire only once (at least until it completes). Is there a way to ignore events on createButtonStream until Api.create returns? i.e., the first event should call #Api.create, subsequent events should be ignored until #Api.create returns.

createButtonStream
   .flatMap(() => Api.create()) //Needs to fire once until doSomething() is called
   .onValue(result => doSomething(result))

The only way that comes to mind is to use global state...and I'd rather not do that.

//i don't wanna do this
let condition = true

createButtonStream
   .filter(() => condition)
   .map(() => condition = false)
   .flatMap(() => Api.create())
   .onValue(result => {condition = true; doSomething(result)})

Upvotes: 5

Views: 929

Answers (2)

paulpdaniels
paulpdaniels

Reputation: 18663

In RxJS you use the flatMapFirst or exhaustMap operator (if using RxJS 5)

createButtonStream
   .flatMapFirst(() => Api.create())       
   .subscribe(result => doSomething(result));

flatMapFirst will silently drop events if they arrive before the first source completes, the method should not get invoked.

Upvotes: 3

OlliM
OlliM

Reputation: 7113

You can use awaiting. You need a Bus to work around the chicken and egg problem.

const filterBus = new Bacon.Bus()

const createDone = createButtonStream
  .filter(filterBus.toProperty(true))
  .flatMap(() => Api.create())

const inProgress = createButtonStream.awaiting(createDone)
filterBus.plug(inProgress.not())

createDone.onValue(doSomething)

Upvotes: 0

Related Questions