我正在开发一个用户服务,它通过用户的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调用之前,它不会被实例化和订阅。

10-05 20:51
查看更多