如何防止BehaviourSubject在定义之前被消耗? [英] How do you prevent a BehaviourSubject from being consumed before it's defined?

查看:124
本文介绍了如何防止BehaviourSubject在定义之前被消耗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一种用户服务,该服务通过用户的user_id跟踪用户.它首先检查cookie中是否存在user_id,如果不是,它将向api发出get请求以创建一个新的id,并在响应中返回id.我的问题是,响应完成之前正在消耗user_id.我有两个问题:

I'm working on a user service that keeps track of users by their user_id. It first checks if user_id is present in their cookies, if it isn't it makes a get request to the api to create a new one and returns the id in the response. My problem is that the user_id is being consumed before the response is completed. I have two questions:

  1. BehaviourSubject甚至在被定义为新的BehaviourService之前就已被使用,使用它的组件正在undefined上调用.subscribe(),结果该应用程序崩溃了.
  2. 我每次要检索user_id时真的需要订阅吗?由于我先订阅了behavioursubject,然后在subscribe方法中订阅了代码,因此代码变得难以工作.我想不出一种更好的方法来解决这个问题,从我读过的文章中,他们提到链接流是正确的方法,但这感觉很不对.
  1. The BehaviourSubject is being consumed before it's even defined as a new BehaviourService, components that consume it are calling .subscribe() on undefined as a result and the app is crashing.
  2. Is the really necessary for me to subscribe to the user_id every single time I want to retrieve it? The code is turning into hell to work with since i'm subscribing to the behavioursubject first and then inside the subscribe method I'm writing my code. I can't figure out a better way to go about it, and from the texts I've read they mention that linking streams is the right approach, but this just feels very wrong.

这是我在做什么的简化示例

Here's a simplified example of what I'm doing

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'));
    }
}

在组件中使用常规

constructor(private userService: UserService) {
    data;
    this.userService.ruid.subscribe(
        (value) => {
            this.data = this.http.get(url + value).map(res => res.json())
        }
    );
}

推荐答案

我相信您需要在此处设置路由解析器.在下面的真实项目中查看我的示例:

I believe what you need here is to setup resolver on your route. See my example from real project below:

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进行调用,然后设置位置.

Basically what it does is not resolving route up until it gets the necessary data. In my case I need to query locationId and provide it to every call after login. So resolver either looks for it in LocalStorage or doing a call to the API and then sets the location.

UPD:根据您的情况,您可以将此类解析器放在预订BehaviorSubject的路由上,直到您完成所有API调用后,它才会被实例化和预订.

UPD: In your case you can put such resolver on the route that subscribes to BehaviorSubject and it will not get instantiated and subscribed until you finish all the API calls.

这篇关于如何防止BehaviourSubject在定义之前被消耗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆