I am trying to convert a plain string[]
into a Observable<string[]>
and concat it to an existing Observable<string[]>
.
I will then use an angular2 async
pipe in order to display the Observable
.
Here is my code:
import {Injectable} from "angular2/core";
import {Observable} from "rxjs/Observable";
import 'rxjs/Rx';
@Injectable()
export class AppService {
constructor() {
console.log('constructor', 'appService');
this.constructSomeObservable();
}
someObservable$:Observable <string[]>;
constructSomeObservable() {
this.someObservable$ = Observable.create(observer => {
const eventSource = new EventSource('/interval-sse-observable');
eventSource.onmessage = x => observer.next(JSON.parse(x.data));
eventSource.onerror = x => observer.error(console.log('EventSource failed'));
return () => {
eventSource.close();
};
});
this.someObservable$.subscribe(
theStrings=> {
console.log(theStrings);
//Somehow convert the plain array of strings to an observable and concat it to this.someObservable$ observable...
},
error=>console.log(error)
);
}
}
Can anyone please help?
Furthermore, I want to ensure that the service instance Observable<string[]>
is continuously updated as the EventSource is called repeatedly. Is my subscribe logic in the right place?
edit 1: I tried to use RxJS concat
operator as follows:
this.someObservable$.subscribe(
theStrings=> {
console.log(theStrings);
this.someObservable$ = this.someObservable$.concat(Observable.create(theStrings));
},
error=>console.log(error)
);
}
together with the angular2 async
pipe:
<ul>
<li *ngFor="#s of appService.someObservable$ | async">
a string: {{ s }}
</li>
</ul>
and nothing gets displayed on the page; the strings just get displayed on the console...
What I am getting wrong?
edit 2: The app is available on github here
edit 3: I have taken into account Thierry's advice, especially the use of the async
pipe in order to subscribe as well as the usage of the scan operator.
The only remaining issue now is that I need to click on the router link in order for the strings to render on the template... The template does not update automatically...
See project on github and relevant tag: https://github.com/balteo/demo-angular2-rxjs/tree/36864628/536299
I would leverage the scan
operator to do that. Here is a sample:
@Component({
selector: 'app'
template: `
<div>
<div *ngFor="#elt of someObservable$ | async">{{elt.name}</div>
</div>
`
})
export class App {
constructor() {
this.someObservable$ = Observable.create((observer) => {
const eventSource = new EventSource('/interval-sse-observable');
eventSource.onmessage = x => observer.next(JSON.parse(x.data));
eventSource.onerror = x => observer.error(console.log('EventSource failed'));
return () => {
eventSource.close();
};
})
.startWith([])
.scan((acc,value) => acc.concat(value));
}
}
Here is the corresponding plunkr: https://plnkr.co/edit/St7LozX3bnOBcoHaG4uM?p=preview.
See this question for more details:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With