Mike
Mike

Reputation: 979

Compose event streams with a resettable delay on one of them

I want to change the size of an element while it is being scrolled (touch pan, etc). In order to do that I intend to use touch events as observable sources. The size should grow when user starts to pan the element and should shrink 5s after user stopped.

In other words:
Given the streams of 'start' and 'end' events, immediately do the action on 'start' and delay the action on 'end'. But if during that delay new event 'start' come, the delay should be cancelled.

Here is marble, the best I could do.

PS
Feel free to suggest a better title. I struggle to come up with something descriptive enough.

Upvotes: 0

Views: 55

Answers (2)

BizzyBob
BizzyBob

Reputation: 14740

You could merge your start and end triggers and use debounceTime with filter:

merge(start$, end$).pipe(
  debounceTime(5000),
  filter(event => event === 'end')
);

Here's a little StackBlitz to play with.

Upvotes: 0

Picci
Picci

Reputation: 17762

Assuming that start$ and end$ are the Observable streams representing the start and end events, than I would probably proceed like this

start$.pipe(
   // use tap to implement the side effect of growing the size of an element
   // the event is passed assuming that it contains somehow the reference to the element
   // whose size has to grow
   tap(event => growSize(event)),
   // any time a start event is notified, we pass the control to the end$ stream
   // if a new start event is notified, the subscription to end$ will be unsubscribed
   // a new subscription will be establishes, which means that a new delay will start
   switchMap(() => 
       end$.pipe(
           // delay 5 seconds
           delay(5000),
           // decrease the size of the element as a side effect
           tap(event => decreaseSize(event)),
       )
   )
)
.subscribe()

Upvotes: 1

Related Questions