我在ngFor中使用 async
管道来观察Observable . Observable由访问我的服务器的服务创建,并且在枚举ngFor循环时的加载时间,服务正确地调用服务器 .
现在对于我不理解的部分:当任何结果回来时,一切都按预期发生 . 但是,如果服务器响应说,404,并且没有可用于枚举的结果,则 async
管道会导致服务继续触发请求,相隔毫秒 . 这显然不好 . 这里的设计期望是什么?如何优雅地处理在使用异步管道时返回错误的Observable?
在组件模板中:
<li *ngFor="let person of persons | async">{{person.id}}</li>
在Component主体中:
get persons: Observable<Person[]> {
return this.personService.list();
}
在服务中:
list(): Observable<Person[]> {
if (this.persons && this.persons.length) {
return Observable.from([this.persons]);
} else {
return this.http.get('/person')
.map((response: Response) => response.json())
.map((data: Person[]) => {
this.persons = data;
return data;
})
.catch((error: any) => {
let errMsg = "some error..."
return Observable.throw(errMsg);
});
}
}
}
2 回答
我有一个非常类似的问题,这是由于Angular2变化检测的工作原理 . 有多种解决方案对我有用 .
保存对observable的引用,使其不会更改
现在当你调用
persons
getter时,它总是返回一个Observable
的Observable
实例(例如一个不同的对象),因此Angular会重新评估整个事物,并且在下一个更改检测周期中,它会再次执行,然后再次执行 . ..所以,这是如何解决的:将ChangeDetectionStrategy更改为OnPush
你可能想告诉Angular:“我知道我在做什么,我会在发生一些变化时告诉你自己”:
这两种解决方案都适用于我,我决定采用第二种方法,因为它也是一种优化
Angular会在偶数发生时检查更改 . 这意味着它将调用模板中存在的变量以查看其结果是否发生了变化 .
如果在每次调用时返回不同的对象或数组(即使内容相同),angular将考虑更改内容并刷新模板(从异步管道重新订阅) .
在你的情况下,你称之为“人”,每次不同的观察者都会返回 .
一种解决方案是将observable影响到局部变量,然后在模板中使用此局部变量 . 像这样的东西:
和你的模板
另一种方法是使用装饰器@Memoize,它将缓存方法的结果并为所有对象返回相同的对象 .
https://www.npmjs.com/package/typescript-memoize
保留你的代码,然后将装饰器添加到你的getter中:
额外奖励:您可能希望缓存从服务中收到的最后一个值(原因是您拥有"if condition") . 你应该考虑使用重播(publishLast or publishReplay)