@Component({ standalone: true, selector: "app-mycomponent", changeDetection: ChangeDetectionStrategy.OnPush, template: ` <p>hi</p> <div *ngIf="users$ | async as users; else loadingOrError"> <div *ngFor="let user of users"> {{ user.name }} </div> </div> <ng-template #loadingOrError> <div *ngIf="loadingError$ | async; else loading"> Error loading the list of users. Please try again later. </div> <ng-template #loading>Loading users...</ng-template> </ng-template> `, imports: [CommonModule, HttpClientModule], }) exportclassMyComponent { users$: Observable<User[]>; loadingError$: Subject<boolean> = newSubject<boolean>();
constructor(httpClient: HttpClient) { this.users$ = httpClient.get<User[]>("/api/users").pipe( catchError((error) => { // it's important that we log an error here. // Otherwise you won't see an error in the console. console.error("error loading the list of users", error); this.loadingError$.next(true); returnof(); }) ); } }
exportinterfaceUser { name: string; }
当创建组件时,我们会为 users$ observable 创建一个处理错误状态的 ng template #loadingOrError 和一个接受信息的 observableerrorLoading$。
this.loadingError$ = this.users$.pipe( shareReplay(1), ignoreElements(), // 忽略数据元素,避免数据元素对异常数据流的影响 catchError((error: any) => { // it's important that we log an error here. // Otherwise you won't see an error in the console. console.error("error loading the list of users", error); //this.loadingError$.next(true) returnof(error.message); }) ); } }
/** * The loading wrapper that should be used to show the loading/error state */ @Input() setloadingWrapper(data: Observable<any>) { this.loadingError$ = data.pipe( shareReplay(1), ignoreElements(), catchError((error: any) => { console.log(error.message); returnof(error.message); }) ); }
/** * A configurable error message for error cases. */ @Input() userDefinedMessage: string = ""; }
<div *ngIf="users$ | async as users; else loading"> <div *ngFor="let user of $any(users)"> <p>{{ user.name }}</p> </div> </div>
<ng-template #loading> <loading-or-error #loadingOrError [loadingWrapper]="users$" [userDefinedMessage]="'Error loading the list of users'" ></loading-or-error> </ng-template>
从以上使用方法可以看出,我们依然保持了 async pipe 的写法,对 html template, 中 async pipe 部分没有任何侵入性,对数据流的创建过程也没有任何的侵入性。