#javascript #angular #typescript #rxjs #rxjs-observables
#javascript #угловой #typescript #rxjs #rxjs-наблюдаемые
Вопрос:
Я довольно новичок в angular. У меня есть два компонента, а именно компонент заголовка и профиля. Компонент заголовка обрабатывает функциональность входа в систему и поддерживает две информации — данные пользователя, которые являются объектом json, и isLoggedIn, который является логическим значением, которое сохраняет текущее состояние входа в систему. Общий макет страницы профиля-
<header-component>
<profile-component>
Теперь, поскольку компонент заголовка обрабатывает вход в систему. Я хочу избежать повторного написания логики для получения пользовательских данных и статуса isLoggedIn для компонента profile. Итак, я решил написать общую службу под названием profile service, чтобы я мог загружать пользовательские данные и регистрироваться из заголовка и получать доступ к этой информации в компоненте profile. Входные данные в метод loginlogout поступают из компонента заголовка.
Код SharedService —
import { Injectable } from '@angular/core';
import { HttpService } from './https.service';
import { Observable, BehaviorSubject, of as observableOf } from 'rxjs';
import * as _ from 'lodash';
import { HttpHeaders, HttpParams } from '@angular/common/http';
import { BaseService } from './base.service';
@Injectable()
export class ProfileServices{
constructor(){};
userDetailsBS = new BehaviorSubject<any>('original value');
userDetails= this.userDetailsBS.asObservable();
isLoggedIn:boolean;
loginlogout(userDetails:any , isLoggedIn:boolean){
this.userDetails=userDetails;
this.userDetailsBS.next(this.userDetails);
console.log("Value of user details set in profile service",this.userDetails); //debug
console.log(".getValue() method:",this.userDetailsBS.getValue()); //debug
this.isLoggedIn=isLoggedIn;
}
getUserDetails(){
return this.userDetailsBS.getValue();
}
}
После входа в систему из заголовка-component.ts я вызываю метод loginlogout в службе профилей для установки значений. Я также попытался получить доступ к значению, переданному общей службе, используя getUserDetails, который показывает, что объект UserDetails правильно передается общей службе.
Проблема возникает, когда я пытаюсь получить доступ к данным из компонента профиля-
export class ProfileT1Component implements OnInit {
userDetails:any;
constructor(
public profileService: ProfileServices){
this.profileService.userDetails.subscribe((result)=>{
console.log(result);
this.userDetails=resu<
console.log("received user details in profile component constructor: ", this.userDetails);
})
}
}
результат по-прежнему показывает «исходное значение», а не обновленное значение. Это вообще неправильный подход или я неправильно обрабатываю наблюдаемые. Помощь была бы очень признательна.
Комментарии:
1. Вы определенно не хотите
this.userDetails=userDetails;
. Вы хотите только указать тему поведения (желательно, чтобы она была закрытой). Наблюдаемое предназначено только для получения значения, и bs.next сделает это автоматически. ФункцияgetUserDetails
не нужна.2. Привет, я добавил метод getUserDetails, чтобы узнать, могу ли я установить значение в profileservices, что я могу сделать из консоли. в журнале отображается объект json. Однако при подписке на res по-прежнему отображается «исходное значение», а не json в компоненте профиля ie.
3. может ли это быть проблемой синхронизации, т.Е.. я подписываюсь в компоненте профиля до того, как наблюдаемый выдает измененное значение?
Ответ №1:
Вам нужно внести пару изменений в свой сервис, чтобы он заработал. Добавьте providedIn: root
и удалите все объявления из других модулей. Во-вторых, вам не нужно this.userDetailsBS.asObservable()
, и вы можете использовать subscribe напрямую userDetailsBS
. Ваш код будет выглядеть примерно следующим образом.
Обслуживание:
@Injectable({
providedIn: 'root'
})
export class ProfileServices {
constructor() {}
userDetailsBS = new BehaviorSubject<any>('original value');
isLoggedIn: boolean;
loginlogout(userDetails: any, isLoggedIn: boolean) {
this.userDetailsBS.next(userDetails);
this.isLoggedIn = isLoggedIn;
}
getUserDetails() {
return this.userDetailsBS.getValue();
}
}
Компонент:
export class ProfileT1Component implements OnInit {
userDetails: any;
constructor(public profileService: ProfileServices) {
this.profileService.userDetailsBS.subscribe((result) => {
console.log(result);
this.userDetails = resu<
console.log('received user details in profile component constructor: ', this.userDetails);
});
}
}
Комментарии:
1. Наблюдаемое должно быть сохранено (а объект поведения должен быть закрытым), чтобы сделать bs доступным только для чтения извне, а новые значения могут передаваться только через функции службы. В настоящее время может подойти любой старый компонент
profileService.userDetailsBS.next(...)
. Если вы единственный, кто работает с этим, это может не быть проблемой, но в целом это лучший шаблон (например, побочные эффекты в служебных функциях не будут выполняться, если следующее значение передается напрямую).2. о, имеет смысл, но по какой-то причине он нарушает наблюдаемый подход, есть ли способ исправить это?
Ответ №2:
реализация, похоже, в порядке
(за исключением того, что вы должны сделать BehaviorSubject закрытым и предоставлять только наблюдаемое)
возможно, у вас есть несколько экземпляров службы.
попробуйте добавить :
@Injectable({
providedIn: 'root',
})
и удалите объявление службы из всего массива поставщиков модулей
Комментарии:
1. Привет, я попробовал ваш подход, он не решил проблему. После подписки на наблюдаемый console.log (res) по-прежнему показывает «исходное значение», а не объект json.
2. Нормально получать «исходное значение» в момент подписки, потому что BS возвращает последнее переданное значение (или значение по умолчанию), но после вызова loginlogout из другого компонента вы получили новое значение?
3. компонент заголовка вызывает метод loginlogout, который задает isLoggedIn и UserDetails. Консоль метода getUserDetails регистрирует неявность входных данных при получении. Служба профилей получает json. Компонент профиля вызывается только после этого. Поскольку подписка происходит в конструкторе и вызывается только один раз, она не отражает измененное значение. console.log(res) отображает только исходное значение.
4. вы на 100% уверены, что экземпляр службы в компоненте, вызывающем loginlogout, совпадает с экземпляром компонента, который подписывается на наблюдаемый? поскольку в момент подписки значение наблюдаемого уже изменено, вы должны немедленно получить новое значение