背景:
具有嵌套组件和服务的复杂角度特征模块。顶级组件订阅要通知的主题,并通知模块中捕获的错误。
问题:
所有顶级组件接收错误通知(因为它们订阅了subject.next消息)并作出反应。
实现的解决方案:
通过“指纹”进行过滤,但这需要所有服务中的所有方法,这些方法与.catch()连接起来,才能添加一个“指纹”参数。
例如:
...
@Injectable()
export class SharedService {
getSth (idOfWhatToGet: string, fingerprint: string) { // <<< !!! fignerprint
this.http.get('myurl')
.toPromise()
.then(a => a)
.catch(err => this.subject.next({err, fingerprint}); // <<< !!!
}顶层组件:
...
@Component({...})
export class SomeTopLevelComponent {
@Output() onError = new EventEmitter<Error>();
private myFingerprint = 'STL_component';
...
this.subject.subscribe(errMsg => errMsg.fingerprint === 'myFingerprint ' ?
this.onError = errMsg.err); // <<< !!! fingerprint filtered
}有办法区分哪个组件称为服务吗?
如果没有,还有什么比在每个服务调用中添加“指纹”参数更好的解决办法呢?
详细信息
让我们假设有一个使用功能UI模块的角项目,它包括:
通常使用特征模块公开的元素(顶层组件):
<my-angular-project>
<feature-el-1 (onError)="callErrHandler($event)></feature-el-1>
<feature-el-2 (onError)="callErrHandler($event)></feature-el-2>
<my-angular-project>特性-el-1和功能-el-2组件都订阅了传入的错误消息:
OnInit() {
this.subjectSubscription = this.errorService.getErrorsMessages()
.subscribe(errorMessage => this.onError.emit(errorMessage.err));
}以及所有服务分派错误,当捕捉到这些错误时:
...
doSth.then(p => ...)
.catch(err => this.errorService.sendErrorMessage({err})错误服务的实现类似于:
@Injectable()
export class errorService {
private subject = new Subject<any>();
sendErrorMessage(message: {err: Error}) {
this.subject.next(message);
}
getErrorsMessages(): Observable<any> {
return this.subject.asObservable();
}
}现在,<feature-el-1>和<feature-el-2>通过在同一个服务上调用一个方法来加载它们的数据,比如getAddresses()。接下来会发生什么:从<feature-el-1>启动的调用成功,来自<feature-el-2>的调用失败。但是-- <feature-el-1>和<feature-el-2> --都将收到错误,并将引发onError事件(我们只希望其中之一,即服务崩溃的事件)引发事件。
为了解决这一问题,我们使用“指纹”--基于某种逻辑(指示下游哪个顶层组件发生错误)向每个服务方法调用添加了一个参数,以便公开的顶层组件可以决定--是否产生接收到的错误消息。它庞大而繁琐的逻辑代码体,所以所有归结到主要的问题-可以知道(当它知道它可以传回这个知识,象征性地说)哪个组件叫他?。
发布于 2018-06-01 13:56:42
您有一个名为SharedService的服务,它处理后端API的Http请求,并且希望侦听顶级组件中的错误。您希望共享该服务,以便其他组件可以使用它,但您不希望共享错误。
您遇到了这样的问题:当服务发出错误时,您不知道哪个顶级组件负责原始Http请求。
<my-angular-project>
<feature-el-1 (onError)="callErrHandler($event)></feature-el-1>
<feature-el-2 (onError)="callErrHandler($event)></feature-el-2>
<my-angular-project>在上面的示例中,您有两个名为feature-el-1和feature-el-2的特性组件。每个组件只需要发出源自该组件或其子组件之一的错误。
使用组件提供程序
从SharedService提供程序数组中删除NgModule,并将其添加到每个功能组件的提供程序数组中。
@Component({
selector: 'feature-el-1',
providers: [SharedService],
template: '<child-feature></child-feature>'
})
export class FeatureElOneComponent {
@Output() onError: Observable<Error>;
constructor(service: SharedService) {
this.onError = service.errors;
}
}
@Component({
selector: 'feature-el-2',
providers: [SharedService],
template: '<child-feature></child-feature>'
})
export class FeatureElTwoComponent {
@Output() onError: Observable<Error>;
constructor(service: SharedService) {
this.onError = service.errors;
}
}现在已经为每个组件定义了providers: [SharedService],那么每个组件都会收到该服务的新实例。他们将不会共享相同的服务。
现在,让我们看一下<child-feature>组件。
@Component({
selector: 'child-feature',
template: '<span>Child Feature</span>'
})
export class ChildFeatureComponent {
constructor(service: SharedService) {
service.doSth().then((data)=>console.log(data));
}
}这个组件由两个功能模块使用,但是ChildFeatureComponent的每个实例都接收不同的SharedService实例。因此,当FeatureElOneComponent内部使用的子组件触发错误时,只有该特性组件接收错误。
https://stackoverflow.com/questions/50634338
复制相似问题