可观察状态(UI)
Observable with status (for UI)
我正在尝试创建一个具有状态的可观察对象,以便能够在 UI 中显示加载。
combineLatest 正常工作,管道仅在 switchmap 上以防止可观察对象(combineLatest)在出现错误时关闭
我找到了一个示例 ( or this),说明我应该如何使用有状态可观察对象,但我无法将两者合并,有什么帮助吗?谢谢
我的例子
combineLatest([
Observable_One,
Observable_Two,
Observable_Three,
]).pipe(
switchMap(([R1, R2, R3]) =>
this.MyServiceWithPossibleError(...)
.pipe(catchError(() => { return EMPTY }))))
Web 示例
export enum ObsevableStatus {
SUCCESS = 'Success',
ERROR = 'Error',
LOADING = 'Loading',
}
export interface ObservableWithStatus<T> {
status: string;
data?: T;
error?: Error;
}
export function observableWithStatus<T>(x: Observable<T>): Observable<ObservableWithStatus<T>> {
return x.pipe(
map(x => ({ status: ObsevableStatus.SUCCESS, data: x })),
startWith({ status: ObsevableStatus.LOADING }),
catchError(x => {
return of({ status: ObsevableStatus.ERROR, error: x });
})
);
}
更新
- 如果“Observable_One”、“Observable_One”或“Observable_Three”发出一些值,则显示加载
- 如果我的服务 (MyWebServiceWithPossibleError) 抛出一些错误,停止加载并显示消息,但没有完成“combineLatest”(长期可观察),所以可以继续接收 3 个可观察的事件
- 如果没有错误,隐藏加载并显示数据
目的不是字面意义上的把两个例子结合起来,而是用两者构建一个例子
更新 2
getEntities$ = combineLatest([
Observable_One,
Observable_Two,
Observable_Three,
]).pipe(
switchMap(
([R1, R2, R3]) =>
concat(
of({ status: 'loading', value: '' }),
this.MyServiceWithPossibleError$(...)
.pipe(map(x => ({ status: 'success', value: SERVICE_RESPONSE })), catchError(() => EMPTY))
)
)
)
<div *ngIf="getEntities$ | async as obs" [ngSwitch]="obs.status">
<div *ngSwitchCase="'success'">
Success! {{ obs.value }}
</div>
<div *ngSwitchCase="'error'">
Error
</div>
<div *ngSwitchCase="'loading'">
Loading!
</div>
</div>
听起来您所缺少的只是您需要将错误映射到实际响应中,而不仅仅是一个立即完成的空流
getEntities$ = combineLatest([
Observable_One,
Observable_Two,
Observable_Three
]).pipe(
switchMap(([R1, R2, R3]) =>
concat(
of({ status: 'loading', value: '' }),
this.MyServiceWithPossibleError$(...).pipe(
map(x => ({
status: 'success',
value: SERVICE_RESPONSE
})),
catchError(err => of({
status: 'error',
value: 'ERROR MESSAGE: ' + err.message
})),
)
)
)
);
我正在尝试创建一个具有状态的可观察对象,以便能够在 UI 中显示加载。
combineLatest 正常工作,管道仅在 switchmap 上以防止可观察对象(combineLatest)在出现错误时关闭
我找到了一个示例 (
我的例子
combineLatest([
Observable_One,
Observable_Two,
Observable_Three,
]).pipe(
switchMap(([R1, R2, R3]) =>
this.MyServiceWithPossibleError(...)
.pipe(catchError(() => { return EMPTY }))))
Web 示例
export enum ObsevableStatus {
SUCCESS = 'Success',
ERROR = 'Error',
LOADING = 'Loading',
}
export interface ObservableWithStatus<T> {
status: string;
data?: T;
error?: Error;
}
export function observableWithStatus<T>(x: Observable<T>): Observable<ObservableWithStatus<T>> {
return x.pipe(
map(x => ({ status: ObsevableStatus.SUCCESS, data: x })),
startWith({ status: ObsevableStatus.LOADING }),
catchError(x => {
return of({ status: ObsevableStatus.ERROR, error: x });
})
);
}
更新
- 如果“Observable_One”、“Observable_One”或“Observable_Three”发出一些值,则显示加载
- 如果我的服务 (MyWebServiceWithPossibleError) 抛出一些错误,停止加载并显示消息,但没有完成“combineLatest”(长期可观察),所以可以继续接收 3 个可观察的事件
- 如果没有错误,隐藏加载并显示数据
目的不是字面意义上的把两个例子结合起来,而是用两者构建一个例子
更新 2
getEntities$ = combineLatest([
Observable_One,
Observable_Two,
Observable_Three,
]).pipe(
switchMap(
([R1, R2, R3]) =>
concat(
of({ status: 'loading', value: '' }),
this.MyServiceWithPossibleError$(...)
.pipe(map(x => ({ status: 'success', value: SERVICE_RESPONSE })), catchError(() => EMPTY))
)
)
)
<div *ngIf="getEntities$ | async as obs" [ngSwitch]="obs.status">
<div *ngSwitchCase="'success'">
Success! {{ obs.value }}
</div>
<div *ngSwitchCase="'error'">
Error
</div>
<div *ngSwitchCase="'loading'">
Loading!
</div>
</div>
听起来您所缺少的只是您需要将错误映射到实际响应中,而不仅仅是一个立即完成的空流
getEntities$ = combineLatest([
Observable_One,
Observable_Two,
Observable_Three
]).pipe(
switchMap(([R1, R2, R3]) =>
concat(
of({ status: 'loading', value: '' }),
this.MyServiceWithPossibleError$(...).pipe(
map(x => ({
status: 'success',
value: SERVICE_RESPONSE
})),
catchError(err => of({
status: 'error',
value: 'ERROR MESSAGE: ' + err.message
})),
)
)
)
);