Компонент не получает обновленные данные при совместном использовании данных между компонентами с помощью сервиса

#angular #typescript #behaviorsubject

#angular #typescript #behaviorsubject

Вопрос:

Я хочу использовать brandName переменную из родственного компонента в другой в том же модуле. Я пытался сделать это с помощью BehaviorSubject

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

мой файл службы выглядит следующим образом:

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

import { BehaviorSubject } from 'rxjs';


@Injectable()

export class DataService {


  private messageSource = new BehaviorSubject('default message');

  currentMessage = this.messageSource.asObservable();


  constructor() { }

  changeMessage(message: string) {

    console.log('service sent: '   message);

    this.messageSource.next(message);

  }

}
  

здесь консоль выводит обновленное сообщение.

однако, когда я пытаюсь обновить свою переменную в компоненте Order, я получаю «сообщение по умолчанию»

Order.component.ts:

 
import {DataService} from '../services/data.service';

...
export class OrderComponent implements OnInit {
...

constructor(...private data: DataService)

...

this.data.currentMessage.subscribe(message => this.brandName = message);

console.log('brandname');

console.log(this.brandName);

  

выводит «сообщение по умолчанию»

только их общий родительский app.module.ts элемент содержит DataService поставщика.

Редактировать

Я попытался также получить переменную из третьего компонента, используя:

this.data.currentMessage.subscribe(сообщение => this.brandName = сообщение);

В этом случае фактически получают обновленное фирменное наименование, но в компоненте, для которого он предназначен, по-прежнему ничего нет, хотя оба компонента являются братьями и сестрами одного уровня.

Кроме того, я попытался переделать службу с помощью

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

@Injectable({
  providedIn: 'root',
})
export class DataService {

  private data: string;

  setOption(value) {

    this.data = value;
    console.log('service sent: '   value   'and data '   this.data );
  }

  getOption() {
    console.log('service returned');
    console.log(this.data);
    return this.data;


  }
  

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

Комментарии:

1. можете ли вы собрать stackblitz, отображающий неправильную функциональность?

Ответ №1:

Попробуйте объявить службу, как показано ниже, чтобы иметь один экземпляр (добавить providedIn: 'root' )

 @Injectable({
  providedIn: 'root',
})
export class DataService {


  private messageSource = new BehaviorSubject('default message');

  currentMessage = this.messageSource.asObservable();


  constructor() { }

  changeMessage(message: string) {

    console.log('service sent: '   message);

    this.messageSource.next(message);

  }
}
  

И поскольку служба вызывается асинхронно, console.log(this.brandName); вызывается до окончания работы службы, поэтому я предлагаю переместить this.brandName значение журнала внутри subscribe:

 this.data.currentMessage.subscribe(message => {
 this.brandName = message;
 console.log(this.brandName); // will show the new message
});

console.log('brandname');

console.log(this.brandName); // will show the default message
  

Я создал приложение Stackblitz, содержащее ваш код и в котором работает общая служба: https://stackblitz.com/edit/angular-ele1cu

Комментарии:

1. Я попытался добавить предоставленный Injectable, но я все равно получаю сообщение по умолчанию.

2. Может ли тот факт, что компонент, в котором я изменяю сообщение, загружается до того, как Order.component подписан на сообщение, означает, что оно не работает?

3. спасибо за ваш ответ, Мохамед, к сожалению, я по-прежнему получаю значение по умолчанию this.data.currentMessage.subscribe(message => { this.brandName = message; console.log(this.brandName); // will show the new message }); , поскольку я отредактировал свой исходный пост с дополнительной информацией

4. из вашего кода я заметил, что вы не вызываете changeMessage метод, я создал рабочий стекблитц: stackblitz.com/edit/angular-ele1cu

Ответ №2:

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

Ответ №3:

Файл службы

 import { Observable, Subject, } from 'rxjs';


@Injectable({providedIn: 'root'})

export class DataService {

  // private messageSource = new BehaviorSubject('default message');
  // currentMessage = this.messageSource.asObservable();

  private messageSource = new Subject<string>();

  constructor() { }

  /*changeMessage(message: string) {
    console.log('service sent: '   message);
    this.messageSource.next(message);
  }*/

  setMessage(message: string) {
    this.messageSource.next(message);
  }

  getMessage() {
    return this.messageSource.asObservable();
  }
}
  

Используйте метод GetMessage в службе, чтобы подписаться на изменения в сообщении в вашем компоненте, и используйте метод setMessage для установки сообщения