private pollSubscriptions: Subscription;
private defaultPollTime: number = 2000;
constructor(
private http: HttpClient,
) {
this.pollSubscriptions = new Subscription();
}
pollRequest<T>(
url: string,
updateStatus: any,
pollWhileCondition: Function,
onPollingSuccessCallback?: Function,
timer = this.defaultPollTime
) {
this.pollSubscriptions.add(timer(0, 2000).pipe(
switchMap(() => this.http.get<T>(url).pipe(
catchError((error: any) => empty()))),
tap(updateStatus),
takeWhile(data => pollWhileCondition(data)))
.subscribe());
}
ngOnDestroy(): void {
this.pollSubscriptions.unsubscribe();
}
我能够同时轮询多个URL。但是如何增强当前功能,以便满足以下要求:
仍然没有解决方案
预先感谢
答案 0 :(得分:2)
希望这会有所帮助。
几件事:
pollWhen
属性。retryWhen
,这是一个很难理解的运算符,但基本上它的工作原理是这样的:当您订阅时,它会以可观察到的潜在错误调用函数,当错误发生时发出时,您应该将其擦洗为“下一个”值以重试,立即完成操作(例如为空)以安静地完成操作,或者通过错误操作(例如throwError)将其杀死,并观察到错误。class Component() {
/** ticks every 10 seconds */
pollWhen = timer(0, 10000)
.pipe(share());
private pollSubscriptions: Subscription;
constructor(
private http: HttpClient,
) {
this.pollSubscriptions = new Subscription();
}
pollRequest<T>(
url: string,
updateStatus: any,
pollWhileCondition: Function,
onPollingSuccessCallback?: Function,
timer = this.defaultPollTime
) {
this.pollSubscriptions.add(this.pollWhen.pipe(
switchMap(() =>
this.http.get<T>(url).pipe(
// Setup retries
retryWhen(
errors => errors.switchMap(
// if more than 3 retries,
// stop retrying quietly
(_, i) => i < 3
? timer(1000)
: EMPTY
)
)
)
),
tap(updateStatus),
takeWhile(pollWhileCondition)
).subscribe());
}
ngOnDestroy(): void {
this.pollSubscriptions.unsubscribe();
}
}
答案 1 :(得分:0)
要回答第一个问题,可以使用retryWhen运算符并替换catch。 对于2个问题,方法需要重新编写一点,您可以将pollRequest更改为subject()来存储并向流发送不同的URL进行处理。
var pollUrl = new rxjs.Subject()
const updateStatus = () => true
const pollWhileCondition = () => true
const http = url => {
console.log('http call...',url)
return rxjs.timer(1000).pipe(
rxjs.operators.tap(()=>{
throw "http call error"
})
)
}
const distinctUrl = pollUrl.pipe(rxjs.operators.distinct())
distinctUrl.pipe(
rxjs.operators.mergeMap(url => {
return rxjs.timer(0, 2000).pipe(rxjs.operators.map(() => url))
}),
rxjs.operators.tap(()=>console.log('xxx')),
rxjs.operators.mergeMap(url => http(url).pipe(
rxjs.operators.retry(3),
)),
rxjs.operators.catchError(()=>rxjs.empty()),
rxjs.operators.repeat()
).subscribe(()=>{},err=>{
console.warn(err)
},()=>console.log('comple'))
pollUrl.next('http://google.com')
setTimeout(()=> pollUrl.next('http://twitter.com') ,7000)
答案 2 :(得分:0)
这不是完整的解决方案,但是在这里,我能够实现3次重试3次(延迟3秒)。我仍在寻找如何区分活动投票URL的方法。非常感谢您的帮助。
import { timer as observableTimer, Subscription, interval, of, concat, Observable } from 'rxjs';
import { takeWhile, tap, take, switchMap, repeat, retryWhen, scan, mapTo, expand, exhaustMap } from 'rxjs/operators';
@Injectable()
export class ReportPollingService {
private pollSubscriptions: Subscription;
constructor(private http: HttpClient){}
pollRequest<T>(url: string, updateStatus: any, pollWhileCondition: Function){
if (this.pollSubscriptions.closed) {
this.pollSubscriptions = new Subscription();// re-open polling
}
const request$ = this.http.get<T>(url);
const firstRequest$ = request$;
const polling$ = interval(options.interval).pipe(
take(1),
exhaustMap(() => request$),
repeat()
);
this.pollSubscriptions.add(concat(firstRequest$, polling$).pipe(
retryWhen(errors$ => {
return errors$.pipe(
scan(
({ errorCount, error }, err) => {
return { errorCount: errorCount + 1, error: err };
},
{ errorCount: 0, error: null }
),
switchMap(({ errorCount, error }) => {
if (errorCount >= 3) {
throw error;
}
return observableTimer(3000, null);
})
);
}),
).pipe(tap(updateStatus), takeWhile(data => pollWhileCondition(data))).subscribe());
}
stopPolling(): void {
this.pollSubscriptions.unsubscribe();
}