Reputation: 6798
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
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
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