函数在内部异步结果完成之前返回值
问题描述:
我试图向我的服务添加一个帮助器方法,该方法将在返回Observable的同一服务中调用另一个方法。辅助方法需要返回一个布尔值。问题是确定返回值是true还是false是在显然是异步的订阅块内完成的。所以即使通过这个值是真的我仍然总是得到一个虚假的回报。也许试图混合同步和异步编程这不是一个好方法。函数在内部异步结果完成之前返回值
在我的部分我想作以下调用服务:
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();
}
);
}
这工作得很好,直到我不得不重复上的其他组件这个相同的逻辑。所以我试图想出一种方法将该逻辑抽象为服务本身返回一个布尔值,因为这是我真正需要的函数。
我已经尝试了一些想法,但他们都没有工作。任何帮助都会很棒。谢谢。
答
您也可以将所有控制进入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运营商在这个函数。
通过移动此逻辑并将您的自定义控制流程替换为平台提供的功能,可以减少代码正在执行的认知过载。这也减少了您的测试负担,因为您不必测试框架提供的逻辑。
答
落下投票哪个烂,因为没人告诉过你为什么。如果你不要求他们说出原因,让人们投票的能力似乎是不合逻辑的。你如何期待任何人学习这种方法。
反正我发布解决方案。
我改变了呼叫的组件:
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;
});
}