如何防止BehaviourSubject被定义之前被消费?

时间:2017-11-08 02:11:47

标签: angular rxjs

我正致力于通过user_id跟踪用户的用户服务。它首先检查其cookie中是否存在user_id,如果它没有向api发出get请求以创建新的请求并在响应中返回id。我的问题是在响应完成之前消耗了user_id。我有两个问题:

  1. 在将BehaviourSubject定义为新的BehaviourService之前,它正在被消费,使用它的组件正在调用undefined上的.subscribe(),导致应用程序崩溃。
  2. 我每次想要检索它时,是否真的有必要订阅user_id?由于我首先订阅了行为主题,然后在订阅方法中编写了我的代码,因此代码变成了地狱。我无法找到更好的方法来解决它,从我读过的文本中他们提到链接流是正确的方法,但这只是感觉非常错误。
  3. 以下是我正在做的事情的简化示例

    获取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())
            }
        );
    }
    

1 个答案:

答案 0 :(得分:3)

我相信你需要的是在路线上设置解析器。请参阅以下实际项目中的示例:

<强> resolver.ts

@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: [...]
}

基本上它的作用是在获得必要的数据之前不解决路由。在我的情况下,我需要查询locationId并在登录后将其提供给每个调用。因此解析器要么在LocalStorage中查找它,要么调用API然后设置位置。

UPD:在你的情况下,你可以将这样的解析器放在订阅BehaviorSubject的路由上,并且在完成所有API调用之前它不会被实例化和订阅。