我试图在我的服务中添加一个帮助方法,该方法将在同一个服务中调用另一个返回Observable的方法。辅助方法需要返回一个布尔值。问题是确定返回值是真还是假所需的逻辑是在订阅块内完成的,这显然是异步的。所以,即使价值是真的,我仍然总是得到一个假的回报。也许尝试混合这样的同步和异步编程并不是一个好方法。
在我的组件中,我尝试对服务进行以下调用:
this.isAdmin = this.teamsService.isAdmin(this.teamId, this.user['userId'])
服务:
getAssociations(id, postfix) {
return this.httpService.get(this.base, id, postfix)
.map((response) => {
return this.responseHandler.handleData(response);
})
.catch((error) => {
return this.responseHandler.handleError(error);
}
);
}
isAdmin(teamId, userId) {
let isAdmin = false;
this.getAssociations(teamId, '/teamMembers')
.subscribe(
_data => {
if (_data['teamMembers']) {
for (let i = 0; i < _data['teamMembers'].length; i++) {
if (_data['teamMembers'][i]['id'] === userId) {
isAdmin = true;
break;
}
}
}
}
);
return isAdmin;
}
因此,isAdmin方法总是返回false,原因很明显。我最初通过执行以下操作来处理组件内部的逻辑:
private checkIsAdmin() {
this.teamsService.getAssociations(this.teamId, '/teamMembers')
.subscribe(
_data => {
if (_data['teamMembers'] && _data['teamMembers'].length) {
_data['teamMembers'].map(member => {
if (member['id'] === this.user['userId']) {
this.isAdmin = true;
}
});
}
this.spinner.hide();
this.loading = false;
},
_error => {
this.spinner.hide();
}
);
}
这很好用,直到我不得不在其他组件上重复相同的逻辑。所以我试图找到一种方法将该逻辑抽象到服务本身返回一个布尔值,因为这实际上是我需要的所有功能。
我尝试了一些想法,但没有一个有效。任何帮助都会很棒。感谢。
答案 0 :(得分:0)
因为没有人告诉你原因,所以投票很糟糕。如果你不要求他们说出原因,那么给人们投票的能力似乎是不合逻辑的。您如何期望任何人都能学习这种方法。
无论如何我发布了一个解决方案。
我将组件中的调用更改为:
this.teamsService.isAdmin(this.teamId, this.user['userId'])
.subscribe(response => {
this.isAdmin = response;
}
);
并将服务内的方法更新为:
isAdmin(teamId, userId) {
return this.getAssociations(teamId, '/teamMembers')
.map(_data => {
let isAdmin = false;
if (_data['teamMembers']) {
for (let i = 0; i < _data['teamMembers'].length; i++) {
if (_data['teamMembers'][i]['id'] === userId) {
isAdmin = true;
break;
}
}
}
return isAdmin;
});
}
答案 1 :(得分:0)
您也可以将所有控制逻辑向上移动到Rx流中,如下所示:
isAdmin(teamId, userId) {
return this.getAssociations(teamId, '/teamMembers')
.mergeMap(data => data['teamMembers'] != null ? Rx.Observable.empty() : Rx.Observable.from(data['teamMembers']))
.filter(user => user['id'] === userId)
.mapTo(true) // found admin user
.take(1)
.concat(Rx.Observable.of(false));//default state; no admin user
}
根据getAssociations()
的用法,您还可以将其返回类型签名从Observable<ResponseTeamWrapperSomething>
更改为Observable<TeamMember>
,这样您就可以在此函数中丢失mergeMap运算符。
通过移动此逻辑并使用平台提供的功能替换自定义控制流,可以减少代码正在执行的操作的认知过载。这也减轻了您的测试负担,因为您不必测试框架提供的逻辑。