Как обмениваться данными между сервисами и компонентами angular? - PullRequest
1 голос
/ 12 марта 2019

Как связывать данные между сервисами и компонентами в режиме реального времени.

Давайте предположим, isAuthenticated открытая переменная для службы аутентификации, которая влияет на некоторое представление в компоненте.У меня вопрос, как подписаться на переменную isAuthenticated?

Служба:

import { Injectable } from '@angular/core';

@Injectable()
export class Authentication {

  isAuthenticated:boolean = false;

  login() {
    localStorage.setItem('access_token', 'true');
    this.isAuthenticated = true;
  }
}

Компонент:

...
@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
private isAuthenticated:boolean = false;
  constructor(public authService: Authentication) { 
   this.isAuthenticated = this.authService.isAuthenticated'
  }
}

home.html

...
<div *ngIf="isAuthenticated">Authentication view</div>
<div *ngIf="!isAuthenticated">Unauthentication view</div>
...

При указанном выше потоке привязка работаетхорошо, но не в режиме реального времени.

Итак, что является лучшим подходом:

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

2 - Связывание с использованием следующего способа:

...
<div *ngIf="authService.isAuthenticated">Authentication view</div>
<div *ngIf="!authService.isAuthenticated">Unauthentication view</div>
...

Второй подход работает хорошо, но я не знаю, является ли это наилучшей практикой.

Спасибо.

Ответы [ 3 ]

3 голосов
/ 12 марта 2019

Я бы порекомендовал использовать BehaviorSubject. Это Observable, поэтому вы можете подписаться на него, но вы также можете контролировать, когда он генерирует новые значения, вызывая behaviorSubject.next(newValue). При создании BehaviorSubject вы должны передать ему начальное значение. В вашем случае это false.

@Injectable()
export class Authentication {

  isAuthenticated = new BehaviorSubject<boolean>(false);

  login() {
    localStorage.setItem('access_token', 'true');
    this.isAuthenticated.next(true);
  }

}

-

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  private isAuthenticated:boolean;

  constructor(public authService: Authentication) { 
   this.authService.isAuthenticated
    .subscribe(isAuthenticated => this.isAuthenticated = isAuthenticated)
  }

}

или вы можете подписаться на html с помощью Async Pipe

export class HomePage {

  private isAuthenticated: BehaviorSubject<boolean>;

  constructor(public authService: Authentication) { 
   this.isAuthenticated = this.authService.isAuthenticated;
  }

}

-

<div *ngIf="isAuthenticated | async">Authentication view</div>
<div *ngIf="!(isAuthenticated | async)">Unauthentication view</div>

В отличие от обычного Observable, когда вы вызываете подписку на BehaviorSubject, функция, которую вы передали в качестве аргумента для подписки, будет немедленно выполнена. Это потому, что BehaviorSubject всегда имеет значение. Вы можете получить к нему доступ с помощью this.authService.isAuthenticated.value, но здесь это не очень полезно.

0 голосов
/ 12 марта 2019

Используйте RXJS.Использование BehaviourSubjects позволяет выдвигать состояние и подписываться на изменения состояния во многих компонентах, которые внедряют службу и имеют начальное состояние.При определении BehaviourSubject вы также должны определить начальное значение, которое здесь является ложным.Все, что вам нужно сделать, это вызвать .next(true) в BehaviourSubject для отправки состояния, как показано ниже:

...
@Injectable()
export class Authentication {

  private _isAuthenticated: BehaviourSubject<boolean> = new BehaviourSubject(false);

  public get isAuthenticated(): Observable<boolean> {
    return this._isAuthenticated.asObservable();
  }

  login() {
    localStorage.setItem('access_token', 'true');
    this._isAuthenticated.next(true);
  }
}

Использование метода get в вашем сервисе позволяет вам возвращать наблюдаемое без публичного представления методов в BehaviourSubject..

Тогда в вашем компоненте:

...
@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage implements OnInit {
  private isAuthenticated:boolean = false;
  private readonly _authService: Authentication;
  constructor(authService: Authentication) {
    this._authService = authService;
  }

  public ngOnInit(): void {
   this._authService.isAuthenticated
     .subscribe((isAuthenticated) => this.isAuthenticated = isAuthenticated)
  }
}
0 голосов
/ 12 марта 2019

Я предполагаю, что из вашего тега вы используете Ionic Framework?Может ли это быть сделано с помощью событий?

    // first page (publish an event when a user is created)
constructor(public events: Events) {}
createUser(user) {
  console.log('User created!')
  this.events.publish('user:created', user, Date.now());
}


// second page (listen for the user created event after function is called)
constructor(public events: Events) {
  events.subscribe('user:created', (user, time) => {
    // user and time are the same arguments passed in `events.publish(user, time)`
    console.log('Welcome', user, 'at', time);
  });
}

Пример кода взят из: https://ionicframework.com/docs/v3/api/util/Events/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...