开发者问题收集

无法读取未定义角度的属性“订阅”

2018-10-04
10726

我有一个服务 UserService ,它有一个方法 getUsers() ,并且这个服务在不同的角度组件之间共享。

该方法调用一个 API 并返回数据。我想保存最后一个 API 调用的结果/状态,所以我使用 BehaviorSubject 来保存最后一个状态,这样如果不同的组件调用 getUsers() ,应该只有一个 API 调用,否则必须返回保持状态。

这就是我实现它的方式

private _users$: BehaviorSubject<User[]>;

constructor(private http: HttpClient) {
    this._users$ = new BehaviorSubject([]);
}

getUsers(): BehaviorSubject<User[]> {
    if (!this._getUsersState().length) {
        this._loadUsers();
        this._users$.subscribe(() => {
            return this._users$;
        });
    } else {
        return this._users$;
    }
}

_loadUsers() {
    let _users$ = this.http.get(`${this._context}/users/`);
    _users$.subscribe((users: User[]) => {
        this._users$.next(Object.assign([], users));
    });
}

_getUsersState(): User[] {
    return this._users$.getValue();
}

在组件中

this.userService.getUsers().subscribe((users: any) => {
    console.log(users);
});

但我收到以下错误

ERROR TypeError: Cannot read property 'subscribe' of undefined

我猜如果长度为 0,获取用户会自动返回。

我该如何解决这个问题?这种方法好吗?

2个回答

像这样编辑您的服务:

private _users$ = new BehaviorSubject<User[]>(null);
public usersChanged = this._users$.asObservable();

constructor(private http: HttpClient) {
}

getUsers(): BehaviorSubject<User[]> {
    if (!this._getUsersState().length) {
        this._loadUsers();
        this._users$.subscribe(() => {
            return this._users$;
        });
    } else {
        return this._users$;
    }
}

_loadUsers() {
    let _users$ = this.http.get(`${this._context}/users/`);
    _users$.subscribe((users: User[]) => {
        this._users$.next(Object.assign([], users));
    });
}

_getUsersState(): User[] {
    return this._users$.getValue();
}

像这样编辑您的组件逻辑:

this.userService.usersChanged
.subscribe((users: any) => {
  if(!!users){
    console.log(users);
  } else {
    console.log("No user found!");
  }
});

最好有一个变量作为您的 private behaviorSubject 的可观察变量。因此,您只需订阅它,并且每当其状态发生变化时,它就会发出。

Jacopo Sciampi
2018-10-04

getUsers 方法应返回可观察对象,在服务中订阅可观察对象并不是一个好习惯。 如果您想维护用户状态,请使用单例服务。在服务中声明属性,如下所示:

public users: Users[] = [];


private getUsers(): Observable<Users[]> {
 if (!this.users.length) {
   return this.http.get(`${this._context}/users/`);
 }
 return Observable.of(this.users);
}

在您的组件中

this.userService.getUsers().subscribe((users: User[]) => {
    this.userService.users = users; // (or users.slice(0)
    console.log(users);
});
Sandip Jaiswal
2018-10-04