5

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)})
U Avalos
  • 5,553
  • 6
  • 38
  • 67
  • In kefir you can try to use flatMapFirst – iofjuupasli May 25 '16 at 13:19
  • @iofjuupasli if i'm not mistaken, flatMapFirst will still fire Api.create...it'll just ignore responses until the first one finishes. So in other words, it'll still make calls to the database... which is what I'm trying to prevent. – U Avalos May 25 '16 at 15:26
  • It seems that it's not ```var source = Kefir.sequentially(100, [1, 2, 3]); var result = source.flatMapFirst(x => { console.log(x); return Kefir.interval(40, x).take(4); }); result.log(); ``` . Logs to console `1 3` – iofjuupasli May 25 '16 at 17:43

2 Answers2

3

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.

paulpdaniels
  • 16,958
  • 2
  • 46
  • 51
  • Same functionality exists in bacon (https://github.com/baconjs/bacon.js/#observable-flatmapfirst), this answer is better than the one I gave. – OlliM May 26 '16 at 05:36
0

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)
OlliM
  • 6,505
  • 1
  • 32
  • 45