Angular как подписаться на изменения интерфейса?

Я пытаюсь подписаться на свой интерфейс и следить за изменениями, но у меня возникают ошибки.

  1. Получение данных из API и назначение их this.candidateProfile :

     export interface CandidateProfile {
     about: string,
     c_id: {},
     certificates_training: [],
     city: string,
     country: string,
     currency: string,
     email: string,
     expectedpayhourly: boolean,
     expectedpayhourlyend: number,
     expectedpayhourlystart: number,
     expectedpaymonthly: {},
     expectedpaymonthlyend: number,
     expectedpaymonthlystart: number,
     experience: [],
     firstname: string,
     hobbies: {},
     jobskills: [],
     langugaes: {},
     lastname: string,
     personalskills: [],
     photo: string,
     remotework: boolean,
     role: string,
     studies: {},
     willingtorelocate: {},
     willingtorelocatecity: {},
     worktype: string
      }
    

Auth.service.ts :

candidateProfile: Observable<CandidateProfile>;

getProfile(id, token) {
const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${token}`
  })
};

this.http.get(`users/${id}`, httpOptions).subscribe(data => {
  this.candidateProfile = data;
},
  (error) => { console.info(error) },
  () => {
    console.info('got profile', this.candidateProfile);
  })

 }

Компонент.ts :

this.auth.candidateProfile.subscribe( data => {
console.info(data)
})

ошибка :

this.auth.candidateProfile.subscribe не является функцией

candidateProfile в не наблюдаемом, это просто CandidateProfile. Вместо этого вы должны подписаться на функцию getProfile. И добавь RETURN this.http.get
Roberto Zvjerković 02.05.2019 11:50
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
0
1
1 031
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Когда вы подписываетесь на наблюдаемое, вы подписываетесь на его значение, которое не является наблюдаемым. Когда вы делаете:

this.candidateProfile = data;

По сути, вы сохраняете в профиле кандидата значение, полученное из наблюдаемого. Конечно, у этих данных больше нет функции «подписаться», поскольку они не являются наблюдаемыми.

Вы должны хранить в 'this.candidateProfile' сам наблюдаемый объект, а не значение, которое вы получаете от него. Вот так:

this.candidateProfile = this.http.get(`users/${id}`, httpOptions);

Надеюсь, что я помог вам, хорошего дня!

каждый раз, когда вы подписываетесь на candidateProfile, будет выполняться новый запрос ajax, я думаю, это не то, что ожидается.

Yanis-git 02.05.2019 11:57

Почему? Вы будете подписываться на него только один раз, внутри компонента, который вы используете, или если вы используете службу, каждый раз, когда вы подписываетесь на наблюдаемую, возвращаемую вызовом службы. Вы также можете использовать функцию toPromise() для преобразования наблюдаемого объекта в обещание, если вам так удобнее. Обратите внимание, что вы потеряете все преимущества rxjs Observables, если сделаете это таким образом.

Giovanni Orciuolo 09.05.2019 17:26

Цель состоит в том, чтобы получить текущий профиль кандидата. Я предполагаю, что это может потребоваться многим компонентам. В этом случае вы не хотите снова и снова запрашивать сервер для получения этой информации, но можете запросить ее только один раз, а затем использовать кэшированные данные. не нужно переключаться на обещание, просто использовал другой наблюдаемый поток, как это было предложено в моем ответе. Надежда теперь более ясна

Yanis-git 09.05.2019 18:50

Это не всегда лучший способ сделать что-то. Вы не должны возвращать наблюдаемое в свой служебный файл. Стандартная практика заключается в том, чтобы возвращать наблюдаемое на самом компоненте.

Что касается обработки ошибок, вы можете сделать это либо в своем сервисе, либо в своем компоненте. В примере, который я привожу ниже, я буду обрабатывать ошибки компонента.

В вашем сервисе вам нужно будет добавить оператор return:

getProfile(id, token) {
  const httpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`
    })
  };

  return this.http.get(`users/${id}`, httpOptions);
}

На вашем component.ts вы подписываетесь на него, чтобы вернуть наблюдаемое значение:

this.auth.candidateProfile.subscribe( data => {
  console.info(data)
}, error => {
  // handle error
});

Но если я хочу поделиться профилем на всех своих страницах, не подписываясь на него на каждой странице?

Devla 02.05.2019 11:54

В этом случае вы можете вернуть его в качестве наблюдаемого в своем сервисе. Однако вам все равно нужно будет выполнить необходимые действия, чтобы отписаться от него.

wentjun 02.05.2019 11:58
Ответ принят как подходящий

измените свою службу аутентификации, как показано ниже

export class AuthService {
    private _candidateProfile$: BehaviorSubject<CandidateProfile> = new BehaviorSubject(null);

    getProfile(id, token): void {
        const httpOptions = {
            headers: new HttpHeaders({
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${token}`
            })
        };

        this.http.get(`users/${id}`, httpOptions).subscribe(data => {
                this._candidateProfile$.next(data);
            },
            (error) => { console.info(error) },
            () => {
                console.info('got profile', data);
            })
    }

    get candidateProfile$(): Observable<CandidateProfile> {
      return this._candidateProfile$.asObservable();
    }
}

то вы можете использовать следующее:

this.auth.candidateProfile$.subscribe( data => {
console.info(data)
})

Экспликация

Цель состоит в том, чтобы иметь внутреннюю наблюдаемую на этом сервисе, которая будет транслировать ваш текущий профиль кандидата.

В любом месте вашего приложения вы можете подписаться на него и получить последний выбранный профиль без повторного запуска метода getProfile (и запроса ajax под капотом).

чтобы упростить потребление из AuthService, я создал магический геттер, чтобы абстрагировать его.

get candidateProfile$(): Observable<CandidateProfile> {
  return this._candidateProfile$.asObservable();
}

возьмите свой BehaviorSubject и превратите его в простой Observable. В противном случае вы позволите AuthService потребителю перейти к вашему Observable, а это не то, что ожидается.

единственный способ транслировать новые CandidateProfile должен быть здесь:

 this.http.get(`users/${id}`, httpOptions).subscribe(data => {
      this._candidateProfile$.next(data);
 });

Я также рекомендую вам изменить свой getProfile, как показано ниже

getProfile(id, token): Observable<CandidateProfile> {
    // [...]
    this.http.get(`users/${id}`, httpOptions).subscribe(data => {
           this._candidateProfile$.next(data);
        },
        // [...]
    );

    return this.candidateProfile$;
}

Таким образом, вы можете использовать свой класс следующим образом:

// Fetch new profile.
this.auth.getProfile(id, token).subscribe();
// Fetch last requested profile.
this.auth.candidateProfile$.subscribe();

Другие вопросы по теме