我正在开发一个用户服务,它通过用户的id来跟踪用户。它首先检查用户的cookies中是否存在用户的id,如果不存在,则向api发出get请求以创建一个新的id,并在响应中返回id。我的问题是,用户id在响应完成之前被消耗。我有两个问题:
行为主题在被定义为一个新的行为服务之前就被使用了,因此使用它的组件正在调用undefined
上的.subscribe(),应用程序正在崩溃。
每次我想要检索用户id时,是否真的有必要订阅它?由于我先订阅行为主题,然后在编写代码的subscribe方法中订阅,代码变得很难处理。我想不出更好的方法来解决这个问题,从我读过的文章中,他们提到链接流是正确的方法,但这感觉非常错误。
这里有一个简单的例子
获取ruid或创建一个-user.service.ts
constructor(...) {
public ruid: BehaviorSubject<any>;
if(!Cookies.get('ruid')) {
this.http.get(url).subscribe(
(value) => {
this.ruid = new BehaviorSubject(value)
Cookies.set('ruid', value)
}
)
} else {
this.ruid = new BehaviorSubject(Cookie.get('ruid'));
}
}
在组件中使用ruid
constructor(private userService: UserService) {
data;
this.userService.ruid.subscribe(
(value) => {
this.data = this.http.get(url + value).map(res => res.json())
}
);
}
最佳答案
我相信你需要的是在你的路线上设置解析器。下面是我在实际项目中的示例:
解决方案
@Injectable()
export class LocationResolver implements Resolve<any> {
constructor(private locationsApiService: LocationsApiService, private appStorage: AppStorage, private authService: AuthService) {
}
resolve(route: ActivatedRouteSnapshot): Observable<any> {
return new Observable((observer) => {
const sessionData = this.authService.getSessionData();
if (!sessionData.Location) {
this.locationsApiService.getUserLocations().subscribe(
locations => {
sessionData.Location = locations[0].Name;
sessionData.LocationId = locations[0].Id;
this.authService.updateSessionData(sessionData);
this.appStorage.set(AppConstants.storage.userLocations, locations);
observer.next(sessionData.LocationId);
observer.complete();
}
);
} else {
observer.next(sessionData.LocationId);
observer.complete();
}
});
}
}
路线
{
path: 'app',
component: MainComponent,
canActivate: [AuthGuard],
resolve: {
locationId: LocationResolver
},
children: [...]
}
基本上,它所做的是在获得必要的数据之前不解析route up。在我的例子中,我需要查询locationid并在登录后将其提供给每个调用。所以解析器要么在本地存储中查找它,要么调用api,然后设置位置。
upd:在您的情况下,您可以将这样的解析器放在订阅behaviorsubject的路由上,在完成所有api调用之前,它不会被实例化和订阅。