[英]Error handling with Angular2 async pipe
我正在使用 Angular2 異步管道將值流式傳輸到 DOM 中。 這是一個非常簡單的例子:
const stream = Observable.interval(1000)
.take(5)
.map(n => { if (n === 3) throw "ERROR"; return n; });
<div *ngFor="for num of stream | async">
{{num}}
</div>
<div id="error"></div>
我想要做的是顯示 1-5 的序列,但是在錯誤項 (3) 上,以某種方式用錯誤消息填充#error
div。
這似乎需要兩件事:首先是 Angular 異步管道能夠用錯誤來做一些智能的事情,我看不到任何跡象。 查看源碼,顯然是拋出了一個JS異常,看起來不太友好。
其次是在錯誤發生后重新啟動或繼續序列的能力。 我已經讀過catch
和onErrorResumeNext
等等,但它們都涉及另一個將在錯誤時切換到的序列。 這使生成流的邏輯變得非常復雜,我只想在其上放置一系列數字(在這個簡單的示例中)。 我有一種下沉的感覺,一旦發生錯誤,游戲就結束了,可觀察對象已完成,只能用不同的可觀察對象“重新啟動”。 我還在學習 observables; 事實上是這樣嗎?
所以我的問題是雙重的:
是的,您對 catch 運算符以及在發生錯誤后執行某些操作的能力是正確的...
我會利用catch
運算符來捕獲錯誤並做一些事情:
const stream = Observable.interval(1000)
.take(5)
.map(n => {
if (n === 3) {
throw Observable.throw(n);
}
return n;
})
.catch(err => {
this.error = error;
(...)
});
並在模板中:
<div>{{error}}</div>
為了能夠繼續最初的 observable,您需要從發生錯誤的地方開始創建一個新的 observable:
createObservable(i) {
return Observable.interval(1000)
.range(i + 1, 5 - i)
.take(5 - i)
});
}
並在catch
回調中使用它:
.catch(err => {
this.error = error;
return this.createObservable(err);
});
這兩個問題可以幫到你:
1) 不, async
管道訂閱和取消訂閱並返回它接收到的事件。 您需要在它們收到async
管道之前處理錯誤。
2)您可以使用 catch 運算符,當它返回一個可觀察對象時,它的值由.catch(err => Observable.of(-1))
而不是錯誤發出。
您可以使用它來發出一個特殊的“錯誤”值,然后使用諸如*ngIf="num === -1
類的東西以某種特殊方式顯示錯誤值。
您可以在此https://blog.thoughtram.io/angular/2017/02/27/three-things-you-didnt-know-about-the-async-pipe.html上找到更多信息
@Thierry Templier 的答案是正確的,但現在有點過時了。 以下是如何使用最新的 RXJS 進行操作。
this.myObservable$ = this.myService.myFunc().pipe(
catchError(() => of([])) // this will emit [] if the request fails - u could handle this [] emit on error in the service itself
)
然后 HTML 正常:
<div *ngFor="let xxx of (myObservable$ | async)">
</div>
注意 Observable 名稱末尾的 $ 是 Angular 推薦的表示 Observable 的方式。
我遇到了類似的問題,並想出了另一種方法。 我不知道這是否是一個好方法,但它有效。
要在其中顯示可觀察結果的模板:
<div *ngIf="tableData$ | async as tableData; else loader" class="mt-4">
<!-- do something with tableData -->
</div>
<ng-template #loader>
<loading [target]="tableData$"></loading>
</ng-template>
loading
組件:
export class LoadingComponent implements OnInit {
private _errorMessageSubject : Subject<string> = new Subject<string>();
private _errorMessage$ : Observable<string> = this._errorMessageSubject.asObservable();
public get errorMessage$() : Observable<string> { return this._errorMessage$; }
private _target : Observable<any> | null = null;
public get target() : Observable<any> | null { return this._target }
// this input does nothing except catch the error and feed the
// message into the errorMessage subject.
@Input() public set target(o: Observable<any> | null) {
if(o == null) { return; }
this._target = o.pipe(
catchError((error, _) => {
this._errorMessageSubject.next(error);
return of(null);
}),
);
};
constructor() { }
ngOnInit(): void {
}
}
裝載機模板:
<div *ngIf="target && target | async;">
</div>
<div *ngIf="errorMessage$ | async as error; else loading">
<p class="text-danger">{{ error }}</p>
</div>
<ng-template #loading> <!-- simply a spinner icon -->
<div class="d-flex justify-content-center">
<fa-icon [icon]="['fas', 'spinner']" size="6x" [spin]="true"></fa-icon>
</div>
</ng-template>
我不確定它是否是訂閱兩次可觀察對象的好方法,因為訂閱是在需要數據的原始組件和加載器中完成的,但除此之外,這似乎可以正常工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.