Не удается прочитать свойство «подписаться» на неопределенный угол - PullRequest
0 голосов
/ 04 октября 2018

У меня есть сервис 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 ]

0 голосов
/ 04 октября 2018

Метод 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);
});
0 голосов
/ 04 октября 2018

Отредактируйте свой сервис следующим образом:

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 поведенческий объект.Таким образом, вы просто подписываетесь на него, и всякий раз, когда его состояние изменяется, оно излучает.

...