在我的Angular 2.x应用程序中,我有一个订阅服务所公开的observable的组件。目前,可观察数据服务是通过轮询HTTP请求实现的,但这将改为反应式WS实现。我想保留组件中的轮询,所以问题是:一旦我有订阅者,我怎样才能采取行动,比如通过setInterval
进行HTTP轮询?而且,如果没有更多订阅者,我该如何采取行动,例如clearInterval
?
视图是异步更新的:
<div *ngFor="let headline of headlines$ | async">
<md-list-item (click)="onSelect(headline)">
<h4 md-line>{{headline.title}}</h4>
</md-list-item>
<md-divider></md-divider>
</div>
该组件从服务中获取标题:
export class HeadlinesComponent implements OnInit, OnDestroy {
constructor(
private _headlineService: HeadlineService,
) {
}
headlines$: Observable<Headline[]>;
ngOnInit() {
this.headlines$ = this._headlineService.headlines$;
}
}
该服务作为可观察的数据存储实现:
@Injectable()
export class HeadlineService {
constructor(
private _http: Http) {
_init();
}
private _headlines$: BehaviorSubject<Headline[]> =
new BehaviorSubject<Headline[]>([]);
get headlines$(): Observable<Headline[]> {
return this._headlines$.asObservable();
}
private _store: {
headlines: Headline[]
} = { headlines: [] };
private _save(headlines: Headline[]) {
this._store.headlines = headlines;
this._headlines$.next(Object.assign({}, this._store).headlines);
}
}
并通过HTTP更新商店:
private _interval;
private _init() {
let self = this;
this._interval = setInterval(function(){ self._loadHeadlines();}, 5000);
}
private _loadHeadlines(): Observable<Headline[]> {
let self = this;
let observable: Observable<Headline[]> = this._http
.get(url, options)
.map(response => response.json()._embedded.headlines)
.share();
observable.subscribe(
headlines => self._save(headlines)
);
return observable;
}
实施后,标题服务开始轮询建设而不是延迟直到订户在场。为了使生命周期正确,我可以公开服务的_loadHeadlines
功能,并在组件的ngOnInit
被触发(并在ngOnDestroy
中停止)时开始轮询,但是将服务实现细节暴露给组件(当我转到网络套接字实现时,这些细节会发生变化)我需要准确计算订阅者数量。
那么,有没有一个很好的RxJs-ish方法来解决这个问题?
答案 0 :(得分:1)
Observables很懒,只在订阅时才开始工作。当您停止收听时,他们将取消订阅并清理。
您正在寻找的是多播行为,在第一次订阅时将refcounting转换为init,并且只有当没有人订阅才能清理时。这是使用.share()
运算符完成的。
答案 1 :(得分:0)
我没有在Angular中使用RxJS,但是从你的示例代码中可以看出,你可以.create
一个observable来启动轮询间隔并返回清除间隔函数,该函数将在它被调用时被调用。取消订阅。
/*
Increment value every 1s, emit even numbers.
*/
const evenNumbers = Rx.Observable.create(function(observer) {
let value = 0;
const interval = setInterval(() => {
if(value % 2 === 0){
observer.next(value);
}
value++;
}, 1000);
return () => clearInterval(interval);
});
//output: 0...2...4...6...8
const subscribe = evenNumbers.subscribe(val => console.log(val));
//unsubscribe after 10 seconds
setTimeout(() => {
subscribe.unsubscribe();
}, 10000);
以上示例来自learnrxjs.io