4

I've got an application that performs HTTP requests every 2 seconds and updates the view. Problem is, that I have to do some user-triggered CSS animations that take approximately one second and often get broken because Angular updates the DOM while the animation is running.

Im using Akita store and retrieving observables like so:

this.dosingVessels$ = this.dosingVesselsQuery.selectAll().pipe(*needs rxjs operator magic*);

and then displaying them in the component like so:

    <app-solving-vessel *ngFor="let vessel of solvingVessels$ | async"
                    [vessel]="vessel"
                    [ngClass]="{'animation-class': hoverId === vessel.id}">
    </app-solving-vessel>

How could I achieve that while the animation is ongoing:

animate(event, vessel) {
    this.updateView.next(false); // prevent from updating
    this.hoverId = vessel.id; // triggers animation
    timer(1000).subscribe(tick => this.updateView.next(true)); // allow normal updating
}

the view doesnt get updated.

I found out about delayWhen operator, but all examples are with timers and I'm not sure if it is the right way anyway.

Bazinga
  • 10,716
  • 6
  • 38
  • 63
Klemen Fajs
  • 148
  • 2
  • 6

2 Answers2

6

Does debounce support your needs? You can pass it an Observable and your chain will wait until that Observable emits before continuing. If you need it to wait for a specific value, you need to use the filter operator as well.

I'm not sure where exactly in your code this is needed, but it may look like this:

this.dosingVesselsQuery.selectAll().pipe(
    debounce(() => 
        this.updateView
            .pipe(filter(val => val == true))
            .pipe(first())));

EDIT:

It seems your needs would better be supported by debounce. I've edited my post accordingly.

ggradnig
  • 13,119
  • 2
  • 37
  • 61
  • Cheers, your solution works just the way I need it to. Can't give you public +1 due to my low SO score, but your contribution is deeply appreciated! Thanks! :) – Klemen Fajs Aug 28 '18 at 12:53
0

Delaying an observable subscription or delaying an observable itself is the way to help your cause visit this link, which basically shows that the delay happens on for absolute time.So, basically, your code should be like

this.dosingVessels$ = this.dosingVesselsQuery.selectAll().pipe(delaySubscription(1000));

or

this.dosingVessels$ = this.dosingVesselsQuery.selectAll().pipe(delay(1000));
Vaibhav
  • 1,481
  • 13
  • 17
  • I don't think that this can help me. Lets say, that I get data at 0s. Then at 1.5s, user interacts with the page and causes an animation to run. In this case, i must wait for 500ms before updating the page... but what if user interacts with the page at 1.3s or at 1.9s? Then my interval can't be the same? – Klemen Fajs Aug 28 '18 at 12:07