Общий сервис с BehaviorSubject не выдает правильное значение - PullRequest
0 голосов
/ 30 сентября 2019

Я пытаюсь реализовать общий сервис для управления ролями в моем приложении, используя 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 при запуске приложения.

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

1 Ответ

0 голосов
/ 30 сентября 2019

Немного попробывать

Сначала сделайте ваш сервис единичным, используя

@Injectable({ providedIn: "root" })

Затем этот код

currentRole = this._currentRole.asObservable();

Вы должны создать функцию для возвратаданные не определены как переменные типа

   getCurrentRole() {
     return this._currentRole.asObservable();
   }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...