Я пытаюсь реализовать общий сервис для управления ролями в моем приложении, используя Observable
, чтобы из других компонентов вы могли либо изменить текущую роль, но и получать уведомления об ее изменении. У меня проблема в том, что когда я публикую новое значение через службу, компоненты, которые подписываются на наблюдаемое, всегда получают одно и то же значение (начальное). Затем я никогда не получаю новый номер роли и не могу обновить состояние компонента.
Очевидно, у меня есть следующий набор компонентов:
RolesService : Общая служба, которая управляет сменой роли, получает доступные роли изпользовательский токен, управляет сохранением текущей роли для вошедшего в систему пользователя. Он использует localStorage для сохранения индекса роли. Он получает изменения
HeaderComponent : это пример того, как компонент получает изменения для изменения роли, поскольку ему необходимо обновить заголовок пользователя. Он подписывается на наблюдаемое и соответственно изменяет заголовок
EscullRolComponent : И это пример компонента, который меняет роль, которую пользователь использует в настоящее время (по действиюпользователя, конечно). Он имеет несколько кнопок и отправляет сервису новый индекс.
Вот соответствующий код для этой проблемы:
// RolesService file
@Injectable()
export class RolesService {
private _currentRole: BehaviorSubject<Rol> = new BehaviorSubject(null);
currentRole = this._currentRole.asObservable();
private get currentIndex(): number {
const ras = localStorage.getItem('current_role');
// console.log("Guardat aixo: ", ras);
if (ras === '' || ras === null || ras === 'NaN' || ras === '-1' || parseInt(ras, 10) === NaN) {
return 0;
} else {
return parseInt(ras, 10);
}
}
private set currentIndex(val) {
localStorage.setItem('current_role', val.toString());
}
currentToken: NbAuthJWTToken;
constructor(private authService: NbAuthService,
private http: HttpClient) {
// console.log(this.currentRole);
this.authService.getToken().subscribe((token: NbAuthJWTToken) => {
if (token.isValid()) {
this.currentToken = token;
console.log("Executing token change");
this.setRolActual(0);
}
});
}
protected publishCurrentRol(i: number): void {
console.log("Publishing rol id: ", i); // LOG 1
this._currentRole.next(this.getUserRoles()[i]);
}
setRolActual(i: number) {
this.publishCurrentRol(i);
this.currentIndex = i;
}
}
Ниже приведен компонент, которому пользователь должен изменить роль, и который вызывает службу сновая роль.
@Component({
templateUrl: 'escull-rol.component.html',
styleUrls: ['escull-rol.component.scss'],
})
export class EscullRolComponent {
rols: Array<Rol> = [];
actual: number;
constructor( private rolesService: RolesService,
private route: ActivatedRoute,
private router: Router,
private location: Location ) {
this.rols = this.rolesService.getUserRoles();
this.actual = this.rolesService.getRolActualIndex();
}
buttonRolClicked(index: number) {
this.rolesService.setRolActual(index);
this.router.navigate(['inici']);
// console.log('Boto del rol ' + index + ' clicat');
}
}
А вот и заголовок, который меняет свое состояние в зависимости от роли:
@Component({
selector: 'ngx-header',
styleUrls: ['./header.component.scss'],
templateUrl: './header.component.html',
})
export class HeaderComponent implements OnInit {
@Input() position = 'normal';
user: any = {};
picture: string;
client: stream.Client;
logoPath = '';
logoEra = '';
rol: string;
ids: Array<string>;
constructor(private sidebarService: NbSidebarService,
/* ... more injections .. */
private imatgesService: ImatgesService,
private notificacionsService: NotificacionsService) {
this.logoEra = 'assets/images/logoEra.png';
this.authService.onTokenChange()
.subscribe((token: NbAuthJWTToken) => {
if (token.isValid()) {
if (token.getValue()) {
this.user = token.getPayload(); // Posem les dades del token a l'objecte user
// console.log('token changed, changing user in header', token);
}
}
}, error => {
console.error('Error en carregar el token en el header');
throw error;
});
this.rolesService.currentRole.subscribe((rol: Rol) => {
// This subscription here should receive the change from the service
if(rol) {
console.log("Changing rol on header to ", rol.getIndex()); // LOG 2
this.rol = rol.getTitle();
this.ids = rol.getRolIDs();
}
});
this.imatgesService.getProfileImagePath().subscribe((path: string) => {
this.picture = path;
}, (err) => {
this.picture = '';
});
}
}
Я наблюдаю такое поведение: компонент EscullRol вызывает setRolActual(id)
метод с новым идентификатором, а затем служба вызывает свой внутренний метод publishCurrentRole(id)
с тем же id
, поэтому при LOG 1 я могу увидеть ожидаемый выходной результат. Но затем сразу же я вижу выходную форму LOG 2 в компоненте заголовка с неправильным id
, который всегда является числом, которое мы изначально сохранили в localStorage
при запуске приложения.
На самом деле я не знаю, связана ли проблема с тем, как я использую наблюдаемые, с моделью взаимодействия сервис-компонент или с тем, как компоненты и наблюдаемые инициализируются и обрабатываются под углом.