函数在内部异步结果完成之前返回值

问题描述:

我试图向我的服务添加一个帮助器方法,该方法将在返回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; 
    }); 
}