I'm trying to get a base64 from an api. The following code works fine.
private test = null;
ngOnInit() {
this.loadCustomers();
this.test = this.getSiteImage();
}
getSiteImage() {
return this.CustomerService.getCustomerSiteImage('test.com').share();
}
<img class="avatar avatar-xl" src="{{ (test | async)?.image }}" alt="">
But I would rather like to use a function. When I change the code to the following:
getSiteImage(url) {
return this.CustomerService.getCustomerSiteImage(url).share();
}
<img class="avatar avatar-xl" src="{{ (getSiteImage('test.com') | async)?.image }}" alt="">
I like to know why this isn't working and how I can properly achieve this.
---------EDIT:
To help people with the same problem in the future. Just as @thinkinkingmedia suggested. I put the observables in an object with the url as key.
I changed the getSiteImage(url) methode to:
getSiteImage(url) {
if (url in this.imageObservables) {
return this.imageObservables[url];
} else {
this.imageObservables[url] = this.CustomerService.getCustomerSiteImage(url).share();
return this.imageObservables[url];
}
}
The async pipe in angular will subscribe to an Observable or Promise and returns the latest value it has emitted. When a new value is emitted, the async pipe marks the component to be checked for changes. When the component gets destroyed, the async pipe unsubscribes automatically to avoid potential memory leaks.
Any Angular developer worth his salt has gotta admit that the AsyncPipe is quite terrific. If you subscribe() to an Observable or Promise you'll need to unsubscribe() at the end of your component's life cycle to avoid memory leaks. Change detection works splendidly with the async pipe.
Angular's async pipe is a tool to resolve the value of a subscribable in the template. A subscribable can be an Observable , an EventEmitter , or a Promise . The pipe listens for promises to resolve and observables and event emitters to emit values.
Async pipe it`s better in most of the cases because it is in charge to handle the subscription and unsuscription and notify which reactive part of the code is going to be rendered. Also you prevent possible memory leaks.
The reason it's not working is because async
is getting a new observable every time Angular checks the expression for a change.
In your first example:
{{ (test | async)?.image }}
Angular checks the expression which passes the value of the property test
to async
. Asycn then subscribes to the observable and waits for a value. In the next cycle of checking Angular passes the same observable to Async, and Async makes no changes as it's already subscribed.
In your second example:
{{ (getSiteImage('test.com') | async)?.image }}
Angular checks the expression which calls a function that creates an observable. This is passed to async which waits for a response. In the next cycle this gets repeated. Each change detection creates a new observable and the async never gets a chance to yield a result. For every new observable passed to async it unsubscribes to the previous.
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