I am having such a difficulty inserting observable into an array. What am I doing wrong here..
app.component.ts
const secondNavList = [];
this.appService.issuerList$.subscribe(iss => {
iss.forEach(value => {
console.log(value) //prints {name: 'A', id:'1'} {name: 'B', id:'2'}
secondNavList.push({
config: {
label: value.name
id: value.id
},
type: 'button'
});
});
};
console.log(secondNavList) // prints []
//But I want
//(2)[{...}.{...}]
appService.ts
get issuerList$(): Observable<Issuer[]>{
return this._issuerList.asObservable();
}
getIssuerList(){
const url = DBUrl
this.httpService.getData(url).subscribe((data:any[]) => {
let issuerList = [];
data.forEach(x=>{
issuerList.push(<Issuer>{name: x.issuerName, id: x.issuerId.toString()});
});
this._issuerList.next(issuerList)
})
}
Although inside my secondNavList, it contains data but I can't access it.
CodePudding user response:
The fundamental issue you have is that you're trying to display the value of secondNavList before it is actually set in the subscriber. The rxjs streams are asynchronous, which implies that the the callback inside the subscribe method that appends to the list will get executed at some unknown point after subscribe is executed.
More importantly, I'd recommend that you try to take advantage of the map operator and array.map method, as well as the asyncronous pipes.
appService.ts
readonly issueUpdateSubject = new Subject<string>();
readonly issuerList$ = this.issueUpdateSubject.pipe(
switchMap(url => this.httpService.getData(url)),
map((data: any[]) => data.map(x => ({ name: x.issuerName, id: x.issuerId.toString() }))),
shareReplay(1)
);
getIssuerList() {
this.issueUpdateSubject.next(DBUrl);
}
app.component.ts
readonly secondNavList$ = this.appService.issuerList$.pipe(
map(iss => iss.map(value => ({
config: { label: value.name, id: value.id },
type: 'button'
}))
);
- In the appService, instead of having an observable update a subject, I just had a subject emit update requests. Then instead of having to convert the subject to an observable, it just is an observable.
- The shareReplay operator will share the most recently emitted list to any new subscribers.
- Instead of appending to new arrays, I just use the array.map method to map each array element to the new desired object.
- Instead of creating new array outside of the observable, and setting them in subscribe, I use the map operator to stream the latest instances of the arrays.
I find the more comfortable I got with rxjs the less I actually set the values of streams to instances of variables and rarely call subscribe - I just connect more and more streams and there values are used in components via async pipes. It's hard to get your head around it at first (or after a year) of using rxjs, but it's worth it in the end.
CodePudding user response:
The error is because the observable value is an object array, and you want to add this into a simple object.
Try this.
const secondNavList = [];
this.appService.issuerList$.subscribe(iss => {
iss.forEach(value => {
console.log(value) //prints {name: 'A', id:'1'} {name: 'B', id:'2'}
value.forEach(v => {
secondNavList.push({
config: {
label: v.name,
id: v.id
},
type: 'button'
});
});
});
};
console.log(secondNavList) // prints []