客户端应用程序向服务器发送请求,这可能需要很长时间才能完成。请求完成或失败后,客户端应等待一段时间(即10秒),然后再次发送请求。
目前的工作解决方案是:
appRequest = new Subject();
ngOnInit(): void {
this.appRequest.delay(10000).subscribe(() => this.refresh());
this.refresh();
}
refresh() {
this.api.getApplications().subscribe(a => {
this.updateApplications(a);
this.appRequest.next();
},() => this.appRequest.next()
);
}
对此有更优雅的解决方案吗?
修改
我可以定期使用计时器,但除非先前的请求已经完成,否则我不想发送新的请求。只有在上一个请求完成后,我才想等待10秒再次发送请求。这应该无限期重复。</ em>
getApplications()
函数由swagger生成,它在内部使用angular的http客户端库。目前的观察是,除非您订阅Observable
返回的getApplications()
,否则它不会向服务器发送请求。
答案 0 :(得分:4)
repeatWhen()
运算符似乎是为此设计的,但rxjs风格中缺少示例和文档。
这是RxJava的文档(描述也适用于RxJs)RxJava's repeatWhen and retryWhen, explained。
<强>用途强>
使用repeatWhen + delay定期轮询数据:
source.repeatWhen(completed => completed.delay(5000))
您的版本可能
stopRequesting = new Subject();
ngOnInit() {
this.api.getApplications()
.repeatWhen(completed => completed.delay(10000))
.takeUntil(stopRequesting)
.subscribe(a => this.updateApplications(a))
}
ngOnDestroy() {
this.stopRequesting.next(true);
}
<强>演示强>
// log to html output
log = function(x) { document.write(x + "<br />"); };
const stop = new Rx.Subject();
Rx.Observable.interval(500)
.take(2)
.repeatWhen(completed => completed.delay(1000))
.takeUntil(stop)
.subscribe(
x => log(`Next: ${x}`),
err => log(`Error: ${err}`),
() => log('Completed')
);
setTimeout(() => stop.next(true), 10000)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.js"></script>
答案 1 :(得分:0)
您正在寻找interval
operator。
从上面的链接:
// emit value in sequence every 1 second const source = Rx.Observable.interval(1000); // output: 0,1,2,3,4,5.... const subscribe = source.subscribe(val => console.log(val));
答案 2 :(得分:0)
您可以使用.expand()
递归调用您的函数。
var recursiveObservable = this.api.getApplications().delay(10000);
//recursively call
recursiveObservable
.expand((res) => {
//can do something with your res if you want to.
return recursiveObservable;
})
.subscribe();
上述解决方案将:
this.api.getApplications()
请注意,与所有递归函数一样,.expand()
将无限期地重复,直到您实际为其提供终止条件。例如,您可以使用take运算符指定要重复的次数:
recursiveObservable
.expand((res) => {
//can do something with your res if you want to.
return recursiveObservable;
})
.take(10) //stop after 10 repetitions
.subscribe()
或者终端条件可以基于布尔值:
var shouldContinue = true;
recursiveObservable
.expand((res) => {
//you can modify shouldContinue based on your res results.
return shouldContinue? recursiveObservable : Observable.empty();
}) // will terminate when shouldContinue is false
.subscribe()
答案 3 :(得分:0)
此解决方案仍使用Subject
(且不止一次),但不需要其他功能来了解或致电refresh()
:
const retry$ = new Subject();
const autoRetryRequest$ = Observable.of('Kick start')
.merge(retry$)
.mergeMap(() => {
const next$ = new Subject()
this.api.getApplications().delay(10000).subscribe(
value => next$.next(value),
() => retry$.next(),
() => retry$.next()
);
return next$;
})
.subscribe((data) => { this.updateApplications(data); });
注意:
takeUntil
,unsubscribe
,...来阻止它。最好在takeUntil
之前mergeMap
。expand
解决方案非常优雅,如果可能,应予以考虑。但在你的情况下,它不适合,因为请求必须在错误时重复,并且如果您的请求返回多个值,它将会被破坏。需要对这些案件进行特殊处理才能使其正常工作。答案 4 :(得分:0)
repeat
和 delay
的解决方案看起来更容易理解:
unsubscribe = new Subject();
ngOnInit() {
this.api.getApplications()
.pipe(
delay(10000),
repeat(),
takeUntil(this.unsubscribe))
.subscribe(a => this.updateApplications(a))
}
ngOnDestroy() {
this.unsubscribe.next(true);
}