Компонент Angular 2 прослушивает изменения в сервисе

У меня простой вопрос об обнаружении изменений.

У меня есть компонент и (глобальная) служба с логическим значением внутри. Как я могу заставить компонент слушать это логическое значение и выполнять функцию, если это логическое значение изменится?

Спасибо!


person Han Che    schedule 28.03.2016    source источник
comment
См. angular.io/docs/ts/latest. /поваренная книга/   -  person Mark Rajcok    schedule 28.03.2016


Ответы (2)


В зависимости от того, как изменится это логическое значение, вы можете представить его как Observable<boolean> в своем сервисе, а затем подписаться на этот поток в своем компоненте. Ваш сервис будет выглядеть примерно так:

@Injectable()
export class MyBooleanService {
    myBool$: Observable<boolean>;

    private boolSubject: Subject<boolean>;

    constructor() {
        this.boolSubject = new Subject<boolean>();
        this.myBool$ = this.boolSubject.asObservable();
    }

    ...some code that emits new values using this.boolSubject...
}

Тогда в вашем компоненте у вас будет что-то вроде этого:

@Component({...})
export class MyComponent {
    currentBool: boolean;

    constructor(service: MyBooleanService) {
        service.myBool$.subscribe((newBool: boolean) => { this.currentBool = newBool; });
    }
}

Теперь, в зависимости от того, что вам нужно сделать с этим логическим значением, вам может потребоваться сделать некоторые другие вещи, чтобы ваш компонент обновился, но это суть использования наблюдаемого. Обратите внимание, что в какой-то момент вы захотите отказаться от подписки на поток myBool$, чтобы предотвратить утечку памяти и неожиданные побочные эффекты.

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

person Sam Storie    schedule 28.03.2016
comment
Вы можете получить тему от rxjs - person Sam Storie; 03.06.2016
comment
UserService.ts this._dataService.get<IUser[]>(this._userUrl) .subscribe(users => { self.user = Enumerable.from(users).firstOrDefault(e => e.Email == username && password == "1234"); if (!!self.user) { self._isLoggedInSubject.next(true); } }); Компонент isLoggedIn: boolean; constructor(private _userService: UserService) { this._userService.isLoggedIn.subscribe((response: boolean) => this.isLoggedIn = response); } у меня не работал - person nadav; 03.06.2016
comment
@SamStorie Эй, это можно было бы сделать на 1 строку меньше, объявив Тему следующим образом: private boolSubject = new Subject<boolean>();. Хорошая работа товарищ! ;) - person SrAxi; 12.04.2017
comment
Спасибо. Мне помогло, но я использовал только Subject. Почему ты делаешь this.myBool$ = this.boolSubject.asObservable();? Для меня код также работал, если я сделал boolSubject общедоступным и подписался на него в другом компоненте, то есть service.boolSubject.subscribe((newBool: boolean) => { this.currentBool = newBool; });. По какой причине вы преобразовали Subject в Observable? - person Manu Chadha; 23.05.2018
comment
@ManuChadha Это потому, что я не хотел раскрывать тип Subject клиенту. Это дало бы им возможность продвигать новые значения и могло бы вызвать другие проблемы. В общем, вы хотите использовать Subject для выталкивания значений и строгого предоставления Observables клиентам, которым необходимо подписаться на них. - person Sam Storie; 23.05.2018
comment
Спасибо. Хорошо объяснил. Еще один связанный вопрос (вроде). Есть ли решение проблемы, использующее только Observables? Мне интересно, почему я когда-либо использовал Observable вместо Subject, поскольку Subject кажется более универсальным. Я думал, что смогу сделать Observable.create(observer=>{...}), но полагаю, что полная логика выдачи значений должна быть в блоке {...}, и я не могу выдавать значения из других функций. Я прав? Зачем мне тогда использовать Observable вместо Subject? - person Manu Chadha; 23.05.2018
comment
Ответ задает правильное направление, но забывает реализовать защиту от утечек памяти. Для этого просто назначьте созданный сервис переменной типа Subscription, т.е. subscription: Subscription;, затем в конструкторе установите this.subscription = service.myBool$.subscribe(...), затем в реализованном ngOnDestroy() на компоненте реализуйте this.subscription.unsubscribe(); - person j4v1; 25.03.2019

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

@Injectable()
export class MyBooleanService {
    myBool$: Observable<boolean>;

    private boolSubject: Subject<boolean>;

    constructor() {
        this.boolSubject = new Subject<boolean>();
        this.myBool$ = this.boolSubject.asObservable();
    }

    set myBool(newValue) {
      this._myBool = newValue;
      this.boolSubject.next(newValue);
    }
}
person Thierry Templier    schedule 28.03.2016
comment
Привет, откуда взялся this._myBool? Не могу понять, извините - person Lloople; 09.12.2016
comment
Предполагается, что это частное логическое значение службы, но он просто забыл включить его в свой пример кода. - person Karl Keefer; 05.12.2017