Reputation: 1548
Is there a way to access the 'payload' of an observable directly, and have it resolve later, rather than having to subscribe?
For example, I know we can do this..
export class RecordService
{
fetchRecordFromServer():Observable<Record>
{
return http.get().pipe(map(result => return new Record())); // equivalent
}
}
export class MyComponent
{
public record:Record = null;
constructor(private recordService:RecordService)
{
this.userService.fetchRecordFromServer().subscribe( record =>
{
this.record = record;
});
}
getRecordName():string
{
return this.record? this.record.name || "";
}
}
I was just wondering if there is a shorthand way to do something like this
export class MyComponent
{
public record:Observable<Record>;
constructor(private recordService:RecordService)
{
this.record = this.userService.fetchRecordFromServer();
}
getRecordName():string
{
return this.record? this.record.name || "";
}
}
I'm not entirely sure what I am asking, but I think what I'm after is the idea that a value can be assigned from an Observable of type , and will resolve when the Observable fires, and can be treated as if it was an instance of all along.
Maybe promises can do this, or maybe it's a really stupid question. I just feel like I want to say 'set this variable to be an instance of which will be instantiated at some point soon, but you can try to use it safely straight away, and because the observable is of type it will treat it as that type...
Upvotes: 0
Views: 956
Reputation: 54821
You can use the async
pipe in the template so that there is no subscribe usage inside the component.
export class MyComponent
{
public record$: Observable<Record>;
constructor(private recordService:RecordService)
{
this.record$ = this.userService.fetchRecordFromServer();
}
getRecordName(record: Record):string
{
return record ? record.name : "";
}
}
In the template
<h1>{{getRecordName(records$ | async)}}</h1>
Upvotes: 1
Reputation: 3349
I think by the code you've added that what you're trying to do is tie the UI directly to a hot observable. You can use an Async pipe to do that: https://angular.io/api/common/AsyncPipe
From the documentation:
import { Component } from '@angular/core';
import { Observable, interval } from 'rxjs';
import { map, take } from 'rxjs/operators';
@Component({
selector: 'app-hero-message',
template: `
<h2>Async Hero Message and AsyncPipe</h2>
<p>Message: {{ message$ | async }}</p>
<button (click)="resend()">Resend</button>`,
})
export class HeroAsyncMessageComponent {
message$: Observable < string > ;
private messages = [
'You are my hero!',
'You are the best hero!',
'Will you be my hero?'
];
constructor() {
this.resend();
}
resend() {
this.message$ = interval(500).pipe(
map(i => this.messages[i]),
take(this.messages.length)
);
}
}
Upvotes: 1