Reputation: 213
Here's the sample code on stackblitz
I have a data service that gets it's data asynchronously from a global object (in the real project it emits the data via EventEmitter).
The service looks something like this:
import { Injectable } from '@angular/core';
import { Observable, Observer } from 'rxjs';
class DataEmitter {
public eventCallback: () => void;
constructor() {
setInterval(() => {
if (this.eventCallback) this.eventCallback();
}, 1000);
}
}
let emitter = new DataEmitter();
@Injectable({
providedIn: 'root',
})
export class DataService {
private counter = 1;
public dataSource = new Observable<number>((observer: Observer<number>) => {
emitter.eventCallback = () => {
observer.next(this.counter++);
};
});
constructor() {}
}
The corresponding Component subscribes to the observable and wants to display the data:
import { Component, VERSION, OnInit } from '@angular/core';
import { DataService } from './data.service';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
name = 'Angular ' + VERSION.major;
presentableData: number[] = [];
trigger = 0;
constructor(private dataService: DataService) {}
ngOnInit(): void {
this.dataService.dataSource.subscribe((num) => {
console.log('presentableData.length: ' + this.presentableData.length);
this.presentableData.push(num);
});
setInterval(() => this.trigger++, 10000);
}
}
This doesn't work (doesn't throw an error either) because the global data emitting object is not in the scope of the Observable subscribe method I think. Nonetheless the data will get to the Component and populate the presentableData array (as can be seen in the log output). But the Component will not render again. But if you trigger it via another bound variable, it will show all the data.
I would expect the view to be updated every second and not only when 'trigger' is incremented.
Is my approach completely wrong and this is normal/expected behaviour, or is this a bug with angular?
Upvotes: 0
Views: 484
Reputation:
If your data comes from an event listener, then you have this
scroll$ = fromEvent(window, 'scroll')
Which transforms an event listener into an observable.
Other than that, your data emitter is already covered by RxJS in the form of subjects
obs$ = new BehaviorSubject<number>(0); // Holds the last value and emits it on watch start
obs$ = new Subject<number>(); // don't hold a value, doesn't emit on watch start
Upvotes: 1