我有一项服务,可用于定期获取数据:
export class ApiService {
interval$: BehaviorSubject<number> = new BehaviorSubject<number>(0); // Feed a 0 initially so it makes HTTP call even if auto-refresh is 0
// variable ending in $ is common convention to mean it is an Observable
constructor(private http: HttpClient) { }
getApi(url: string, auto_refresh=false) {
if (!auto_refresh)
return this.http.get(url);
return this.interval$.pipe(
switchMap(duration => {
if (duration == 0)
return this.http.get(url);
return interval(duration * 1000).pipe(
startWith(0),
switchMap(() => this.http.get(url))
)
})
);
}
updateInterval(i: number) {
this.interval$.next(i);
}
}
如果我在类似这样的组件中做某事,这会很棒:
this.subscription = this.apiService.getApi('/api/foo/bar', true).subscribe(tempjson => {
this.foo = tempjson;
});
如果我将自动刷新间隔设置为1,它将每秒获取/api/foo/bar
。
问题在于API是否返回非200
返回码。在这种情况下,它似乎打破了Observable,并且再也没有尝试过再次GET
。
我无法弄清楚这的根本原因。我猜想某种异常正在从Observable中传播出来,并使Observable被破坏。但我不知道如何预防。我尝试向订阅添加错误处理程序,但这没有任何区别:
this.subscriptions.push(this.apiService.getApi('/api/modem/lte_signal_info', true).subscribe(tempjson => {
this.lte_signal_info = tempjson;
},
error => {
console.log(error)
}));
我也尝试捕获服务本身中的错误,但似乎您不能只是吞下该异常,而是必须按照https://angular.io/guide/http#getting-error-details
的要求将其重新抛出。答案 0 :(得分:1)
根据可观察的设计,如果可观察的管道中发生错误(异常),则可观察的处于错误状态,并且无法发出新值(https://blog.angular-university.io/rxjs-error-handling/),并且可以认为已完成[即不能发出新值]。因此,如果API返回非200代码,则您的可观察对象处于错误状态,并且不会发出新值。
现在要在发生错误的情况下保持源可观察的活动状态(在您的情况下,interval
在发生错误的情况下应保持运行状态),请使用catchError
运算符处理可观察的错误并抛出错误。像这样更改代码:
getApi(url: string, auto_refresh=false) {
if (!auto_refresh)
return this.http.get(url);
return this.interval$.pipe(
switchMap(duration => {
if (duration == 0)
return this.http.get(url)
.pipe(
catchError(err => {
//return an observable as per your logic
//for now I am returning error wrapped in an observable
//as per your logic you may process the error
return of(err);
})
);
return interval(duration * 1000).pipe(
startWith(0),
switchMap(() => {
return this.http.get(url)
.pipe(
catchError(err => {
//return an observable as per your logic
//for now I am returning error wrapped in an observable
//as per your logic you may process the error
return of(err);
})
);
})
)
})
);
当然,您可以编写一个函数来放置重复的代码(如上面的代码所示)并使用该方法。
希望它会给您一个想法并解决您的问题。