Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AsyncPipe not working when interval is returned by a function

So I'm messing up a little bit with Observers and I can't understand why methods that returns interval can't display the observers data using the AsyncPipe

component.ts

import {interval} from "rxjs";

export class CalendarComponent implements OnInit {
  interval: any;

  ngOnInit() {
    this.interval = interval(1000);
  }

  myInterval() {
    return interval(1000);
  }
}

component.html

INTERVAL : {{interval | async}} //Displays the interval incrementing each second
FUNCTION : {{myInterval() | async}} //Not working
like image 379
YounesM Avatar asked May 21 '26 04:05

YounesM


2 Answers

If you try

myInterval() {
    console.log('here');
    return interval(1000);
}

you will notice that this function is getting called each 1s. That will give you new object every time (return interval(1000)), hence using just reference is working.

Why this is happening ? (With inputs from @C_Ogoo)

As you are returning interval of 1s, after that the change detection cycle kicks in as you have used interpolation here. Due to this the function gets called again and resulting in new interval every time.

like image 74
Plochie Avatar answered May 22 '26 18:05

Plochie


Every time angular refreshes page by change detector, it checks values/references of bound objects and if there is new one, algorithm puts new values into view. myInterval() method gives reference for new object on every change detection tick. Probable angular has trouble in loading your view. this.interval is all the time same object, so its loaded only once to session cache.

Similar situation is when you would put a PromiseLike type into view like this:

getPromisValue() {
    return Promise.resolve("anything");
}

<p>{{getPromiseValue() | async}}</p>

its all the time the same value but new promise reference so view will have a trouble to load it.

To track such situations, good practise is to inject ngZone in app.component.ts and log onStable observable.

constructor(
    private zone: NgZone
  ) {
    this.zone.onStable.asObservable().subscribe(() => console.log("onStable"));
  }

As angular doc says https://angular.io/api/core/NgZone#onStable it:

Notifies when the last onMicrotaskEmpty has run and there are no more microtasks, which implies we are about to relinquish VM turn. This event gets called just once.

So if you will do something wrong, you will see in console that log occurs too many times. Disable this on production.

like image 20
Michał Dziwota Avatar answered May 22 '26 19:05

Michał Dziwota



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!