在我的网站上,我有一个名为“自动刷新”的全局下拉列表,可让您选择一个轮询间隔:0、1、2、3等,当选择该间隔时,它将导致当前页面的HTTP API为每隔0、1、2、3秒等进行一次轮询。
到目前为止,我已经拥有了:
import { Injectable, Output, EventEmitter } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Rx';
@Injectable()
export class ApiService {
private interval: number = 0;
constructor(private http: HttpClient) { }
autoRefreshObservable() {
if (this.interval > 0)
return Observable.timer(this.interval * 1000);
return Observable.timer(999999999999999);
}
getApi(url: string) {
return Observable.of(null)
.switchMap(e => this.autoRefreshObservable())
.flatMap(() => this.http.get(url))
.repeat();
}
updateInterval(i: number) {
this.interval = i;
}
}
如果我在组件中调用this.apiService.getApi("/api/foo").subscribe(response => {...})
之类的东西,它就可以工作了。如果您将自动刷新设置为0,则在刷新页面之前它将不再起作用。另外,我希望它立即返回第一个响应,但要等待后续响应的间隔。
在服务内部甚至可以做到这一点吗?还是我必须使用它将此逻辑移入组件?
问题是,有很多组件,并且为每个组件添加自动刷新支持将需要大量样板;这就是为什么我希望将逻辑转移到共享服务。
答案 0 :(得分:1)
由于您的持续时间会随着时间而变化,因此我们可以使用BehaviourSubject
将间隔设为可观察的时间。话虽如此,让我们像这样更新ApiService
-
export class ApiService {
interval$: BehaviorSubject<number> = new BehaviorSubject<number>(0);
getApi(url: string) {
return this.interval$
.pipe(
switchMap(duration => {
//From your current code (Observable.timer(999999999999999);), it appears that on duration 0
//You do not want to call API; So this check will take care of that
if (duration === 0) {
//lets not emit anything; i.e. wait for the a NON zero duration
return NEVER;
}
return interval(duration * 1000)
.pipe(
switchMap(() => this.http.get(url))
);
})
);
}
updateInterval(i: number) {
this.interval$.next(i);
}
}
请参见工作示例[只是模拟]-https://stackblitz.com/edit/angular-pi3uaz?file=app%2Fapi.service.ts
希望它能为您解决问题提供一个思路。
答案 1 :(得分:0)
通过对@ user2216584的答案进行一些修改,我可以完全按照自己的意愿进行操作:
getApi(url: string) {
return this.interval$
.pipe(
switchMap(duration => {
if (duration === 0)
return this.http.get(url);
return interval(duration * 1000).startWith(0).pipe(
switchMap(() => this.http.get(url))
);
})
);
}