在我的html中,我正在使用异步管道来订阅如下所示的可观察对象。
<button (click)="getData(1)" >getUser1</button>
<button style="margin:50px;" (click)="getData(2)" >getUser2</button>
<div>------------------------------------------</div>
<div *ngIf="userData$ |async as user">
data is{{ user | json}}</div>
每当用户单击button1或2时,此userData $可观察的值就会变为新值。
getData(id) {
this.userData$ = this.getDataFromBackend(id);
}
getDataFromBackend(id) {
//delay added to simulate network delay
// fake backend call but i have to use real one in actual project
return of(this.dataSource[id]).pipe(delay(1000));
}
现在,每当用户从user1更改为user2时,就会分配新的可观察对象。由于这个新的Observable当时需要一些时间来获取数据,因此显示为空。
我们可以做些什么,以便在不返回新的可观察数据之前,我们可以显示以前的数据。
I can not user loader here meanwhile.
I know i can do something like
let subject = new Subject();
let userObservable$ = subject.asObservable()
and use this observable in the html
and the subscribe to these observable form getDataFromBackend() here in the class and from
subscription do the subject.next() and it will send the updated value
but this does not seem the best way as it do the manual subscription in the component
下面是stackblitz显示问题的链接。
https://stackblitz.com/edit/angular-ivy-d9nsxu?file=src%2Fapp%2Fapp.component.ts
答案 0 :(得分:1)
这是无需手动订阅即可完成此操作的方法:
export class AppComponent {
userData$ :Observable<any>;
dataSource = {1:{user:'user1', id:1}, 2: {user:'user2', id:2}};
private userSrc = new Subject<number>();
ngOnInit () {
this.userData$ = this.userSrc.pipe(
startWith(1),
switchMap(id => this.getDataFromBackend(id)),
)
}
getData(id) {
this.userSrc.next(id);
}
getDataFromBackend(id) {
return of(this.dataSource[id]).pipe(delay(1000));
}
}
答案 1 :(得分:1)
我将使用以下两个选项之一:
选项1
您在数据源(服务,我想是?)上创建另一个Observable(loading$
或state$
),它提供布尔指示(是否正在加载),或者(甚至更好)“状态”(枚举),可以指出它是否处于“初始状态”,“已加载”,“正在加载”等。
选项2
您可以更改通过userData$
可观察的内容流。我建议Observable会介导以下数据结构:
{
user: { ... }, // Containing the user data that has been loaded
state: "Loaded",
}
(加载用户数据时),以及:
{
user: { ... }, // Containing the previously loaded user's data
state: "Loading",
}
(正在加载用户数据时)
嗯,说实话-我很可能会使用类似redux的状态管理系统,例如:
但这是另一个故事
答案 2 :(得分:0)
您可以将else块添加到*ngIf
块中。尝试以下
<div *ngIf="userData$ |async as user; else elseBlock">
data is {{ user | json }}
</div>
<ng-template #elseBlock>
Loading...
</ng-template>
我已经修改了您的Stackblitz
答案 3 :(得分:0)
数据消失的原因是因为您立即用新的可观察对象覆盖了userData$
对象,但尚未返回结果。
也许您可以订阅getDataFromBackend
调用并在返回结果后覆盖userData $:
userData$ = new Subject();
dataSource = {1:{user:'user1', id:1}, 2: {user:'user2', id:2}};
getData(id) {
this.getDataFromBackend(id).subscribe(res => this.userData$.next(res));
}