"return" 使用 Observables 的异步数据
"return" asynchronous data using Observables
假设我的 HTML:
中有这个
<div>
<mat-label>Matched events count: {{(getMatchedEventsCount() | async)?}}</mat-label>
</div>
<div>
<mat-label>Total events count: {{(getTotalEventsCount() | async)?}}</mat-label>
</div>
我的问题是,我从这些辅助方法中 return(就 Observable 而言)是什么?
getMatchedEventsCount(){
return Observable.of(3);
}
getTotalEventsCount(){
return Observable.of(5);
}
但我的问题是 - 我们怎样才能做一些真正异步的事情?
目前,我遇到了这个 HTML 解析错误:
Uncaught Error: Template parse errors: Parser Error: Unexpected end of
expression: Matched events count: {{(getMatchedEventsCount() |
async)?}} at the end of the expression [Matched events count:
{{(getMatchedEventsCount() | async)?}}] in
ng:///AppModule/EventsListComponent.html@40:21 ("
[ERROR ->]Matched events count: {{(getMatchedEventsCount() | async)?}}
"): ng:///AppModule/EventsListComponent.html@40:21 Parser Error: Conditional expression (getMatchedEventsCount() | async)?
requires all 3 expressions at the end of the expression [Matched
events count: {{(getMatchedEventsCount() | async)?}}] in
ng:///AppModule/EventsListComponent.html@40:21 ("
[ERROR ->]Matched events count: {{(getMatchedEventsCount() | async)?}}
"): ng:///AppModule/EventsListComponent.html@40:21
我注意到您已经在评论线程中解决了 ?
的问题。 ?
(称为 "save navigation operator")在那里不起作用的原因是它防止 属性 中的 null
和 undefined
值 路径,这意味着您需要在使用 ?
之后尝试访问 属性。现在你正试图追溯使用它来查看一个对象是null
还是undefined
,但它只能向前看对象,不能向后看,它需要一个属性来寻找。
你是正确的,你应该从方法中 return 一个 Observable
并将其提供给 async
管道。这里有一些关于 async
管道的文档,只是为了彻底:https://angular.io/api/common/AsyncPipe.
关于您在评论线程中关于如何使用 Subscription
而不是 Observable
加载数据的问题...
您可以使用 subscribe
方法并将数据分配给组件上的 属性,如下所示:
matchedEventsSub: Subscription;
matchedEventsCount: number;
getMatchedEventsCount() {
this.matchedEventsSub = Observable.of(3).subscribe(value => {
this.matchedEventsCount = value;
});
}
请注意 subscribe
ing 到 Observable
return Subscription
。然后你必须记住 unsubscribe
从你的 OnDestroy
生命周期钩子中的那个订阅来防止内存泄漏:
ngOnDestroy() {
if (this.matchedEventsSub) { this.matchedEventsSub.unsubscribe(); }
}
您可以想象,当您在一个组件中有 2、3、10 个订阅时,这会变得很麻烦。这就是 Angular 团队创建 async
管道的原因。
最后,
how can we do something actually asynchronous?
其实很简单。假设您有一个 EventsService
注入到您的组件中:
constructor(private eventsService: EventService) {}
该服务可能会封装一个 Http
请求或其他东西 -- Angular 的 HttpClient
模块使用 Observable
s 来表示异步数据。您可以使用 EventsService
获取异步事件流,如下所示:
matchedEventsCount$: Observable<number>;
getMatchedEventsCount(): Observable<number> {
const allEvents$ = this.eventsService.getEvents();
return allEvents$.map(events => events.length);
}
调用 OnInit
生命周期挂钩中的方法来填充数据:
ngOnInit() {
this.getMatchedEventsCount();
}
然后将其显示在您的模板中:
<h1>Events: {{ matchedEventsCount$ | async }}</h1>
假设我的 HTML:
中有这个 <div>
<mat-label>Matched events count: {{(getMatchedEventsCount() | async)?}}</mat-label>
</div>
<div>
<mat-label>Total events count: {{(getTotalEventsCount() | async)?}}</mat-label>
</div>
我的问题是,我从这些辅助方法中 return(就 Observable 而言)是什么?
getMatchedEventsCount(){
return Observable.of(3);
}
getTotalEventsCount(){
return Observable.of(5);
}
但我的问题是 - 我们怎样才能做一些真正异步的事情?
目前,我遇到了这个 HTML 解析错误:
Uncaught Error: Template parse errors: Parser Error: Unexpected end of expression: Matched events count: {{(getMatchedEventsCount() | async)?}} at the end of the expression [Matched events count: {{(getMatchedEventsCount() | async)?}}] in ng:///AppModule/EventsListComponent.html@40:21 (" [ERROR ->]Matched events count: {{(getMatchedEventsCount() | async)?}} "): ng:///AppModule/EventsListComponent.html@40:21 Parser Error: Conditional expression (getMatchedEventsCount() | async)? requires all 3 expressions at the end of the expression [Matched events count: {{(getMatchedEventsCount() | async)?}}] in ng:///AppModule/EventsListComponent.html@40:21 (" [ERROR ->]Matched events count: {{(getMatchedEventsCount() | async)?}} "): ng:///AppModule/EventsListComponent.html@40:21
我注意到您已经在评论线程中解决了 ?
的问题。 ?
(称为 "save navigation operator")在那里不起作用的原因是它防止 属性 中的 null
和 undefined
值 路径,这意味着您需要在使用 ?
之后尝试访问 属性。现在你正试图追溯使用它来查看一个对象是null
还是undefined
,但它只能向前看对象,不能向后看,它需要一个属性来寻找。
你是正确的,你应该从方法中 return 一个 Observable
并将其提供给 async
管道。这里有一些关于 async
管道的文档,只是为了彻底:https://angular.io/api/common/AsyncPipe.
关于您在评论线程中关于如何使用 Subscription
而不是 Observable
加载数据的问题...
您可以使用 subscribe
方法并将数据分配给组件上的 属性,如下所示:
matchedEventsSub: Subscription;
matchedEventsCount: number;
getMatchedEventsCount() {
this.matchedEventsSub = Observable.of(3).subscribe(value => {
this.matchedEventsCount = value;
});
}
请注意 subscribe
ing 到 Observable
return Subscription
。然后你必须记住 unsubscribe
从你的 OnDestroy
生命周期钩子中的那个订阅来防止内存泄漏:
ngOnDestroy() {
if (this.matchedEventsSub) { this.matchedEventsSub.unsubscribe(); }
}
您可以想象,当您在一个组件中有 2、3、10 个订阅时,这会变得很麻烦。这就是 Angular 团队创建 async
管道的原因。
最后,
how can we do something actually asynchronous?
其实很简单。假设您有一个 EventsService
注入到您的组件中:
constructor(private eventsService: EventService) {}
该服务可能会封装一个 Http
请求或其他东西 -- Angular 的 HttpClient
模块使用 Observable
s 来表示异步数据。您可以使用 EventsService
获取异步事件流,如下所示:
matchedEventsCount$: Observable<number>;
getMatchedEventsCount(): Observable<number> {
const allEvents$ = this.eventsService.getEvents();
return allEvents$.map(events => events.length);
}
调用 OnInit
生命周期挂钩中的方法来填充数据:
ngOnInit() {
this.getMatchedEventsCount();
}
然后将其显示在您的模板中:
<h1>Events: {{ matchedEventsCount$ | async }}</h1>