考虑到我有一个 Rest API 列表事件。
这是我的代码。
export function httpFetchRetry<T>(source: Observable<T>): Observable<T> {
let errorScanner = (errorCount: number, error: any) => {
if (errorCount >= 5) throw error;
else if (error.status === 404) throw error;
else return errorCount + 1;
};
return source.pipe(retryWhen(e => {
return e.pipe(scan(errorScanner, 0), delay(3000))
}));
}
export function httpFetchMap<T>(source: Observable<T>): Observable<T[]>{
return source.pipe(map(({data}: any):any[] => data));
}
private listEvents(user_id: string){
let url: string = `${environment.apiEndpoint}/event`;
let payload: any = { user_id };
this.allEvents$ = this.http.post(url, payload)
.pipe(httpFetchRetry)
.pipe(httpFetchMap)
}
该代码与 异步管道 正常工作。
但是,现在我必须在 UI 上显示这些状态之一。
<p> Loading </p>
<p> Loaded </p>
<p> No Data <p>
<p> Error <p>
问题1::如果我使用 n 个异步管道,则会启动 n 个API调用。如何避免这种情况?
第二季度:我如何成为这些状态之一?
目前,我正在解决此问题
.toPromise()
.then(data => {
this.data= data;
this.noDataFound = false;
})
.catch(err => {
if(err.status === 404){
this.noDataFound = true;
}
else{
this.snackBar.open("Something went wrong. Please try again.", null , { duration: 2000 });
}
})
.finally(() => { this.pageLoader = false });
答案 0 :(得分:0)
可观测对象与Promise的不同之处在于,它们直到subscribed
为止都不做。您可以将转换管道链接到Observable,但是原始的Observer
函数只有在包装了Observable
的转换后才能运行。它们与Promises的不同之处还在于,对Observable的每个订阅都将运行Observer函数。
http
方法在完成之前返回一次发射的冷的,有限的Observable。这里的Observer函数是http调用本身。检查您的开发工具,您将发现在订阅Observable之前不会进行http调用。
async
管道实际上subscribe
进入引擎盖下的Observable,并释放其发射值,因此使用该管道将导致Observable运行。同样,toPromise
运算符还订阅源Observable
并将其转换为Promise,因此它的行为类似于Promise,可以立即运行。
通常建议使用async
管道来解包Observable
,但是对于像HTTP请求这样的有限Observable
来说,您可能想解开值并将其保存在外部模板:
private listEvents(user_id: string){
let url: string = `${environment.apiEndpoint}/event`;
let payload: any = { user_id };
this.http.post(url, payload)
.pipe(httpFetchRetry, httpFetchMap)
.subscribe(s => this.allEvents = s);
}
一种好的设计模式是将该值保存在服务中,以供多个组件访问。