[英]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.