I currently have this piece of code. I’m using signals, because I understand that’s the newest way to achieve what I’m trying to achieve, rather than using an observable, or toPromise(), which is deprecated. And I also understand that using async/await syntax is not the way to go about this.
entryArray$ = signal<Entry[]>([]);
getEntryBatch(lemma?: string): Entry[] {
if (lemma) {
this.httpClient
.get<Entry[]>(`${this.url}/entries/l/${lemma}`)
.subscribe((response) => {
this.entryArray$.set(response);
console.log(this.entryArray$()) // this logs the expected response
});
console.log(this.entryArray$()); // this runs too early
} else {
console.log('error catching lemma');
}
console.log(this.entryArray$()); // this runs too early
return this.entryArray$();
}
When I call the function as follows, I don’t get the expected response:
this.resultEntries$.set(
this.entriesService.getEntryBatch(this.searchService.mySearch().letter),
);
I’ve tried changing .subscribe((res) => ... to .pipe(map((res) =>((res) =>... because that’s what some threads suggest I should be doing in a case like this, but couldn’t make it work either. My understanding is that what I need to achieve is for the function getEntryBatch to return a signal, and then subscribe to the signal when I call the function with getEntryBatch(...).subscribe() but I can’t make any of this work.
>Solution :
Try to use effect to trigger the data refresh.
effect(() => {
this.entriesService.getEntryBatch(this.searchService.mySearch().letter).subscribe();
});
Then use a getter to access the signal from the service in the component.
get resultEntries$() {
return this.entriesService.entryArray$;
}
Then you can rewrite the service to.
entryArray$ = signal<Entry[]>([]);
getEntryBatch(lemma?: string): Observable<Entry[]> {
return (lemma ? this.httpClient
.get<Entry[]>(`${this.url}/entries/l/${lemma}`) : of([]))
.pipe(tap((response) => {
this.entryArray$.set(response);
});
}