Rx js Изменение значения субъекта без вызова следующего - PullRequest
0 голосов
/ 08 апреля 2020

Предположим, у меня есть тема поведения в моем сервисе:

theRuleSbj = new BehaviorSubject<Rule>(null);

Затем в моем компоненте я получаю это значение с помощью метода getValue ():

this.rule = this.ruleService.theRuleSbj.getValue();

Тогда, если я изменю некоторые данные в моем локальном объекте правил. например:

this.rule.name = 'name';

Значение моего поведения также меняется без вызова следующего! Кажется, что моя переменная была привязана к субъекту поведения, поэтому каждое изменение в моей локальной переменной будет влиять на мой субъект поведения. Это поведение субъекта поведения? ?? или я что то не так делаю? (Предположим, что я не хочу менять тему поведения при изменении локальной переменной).

Обновление:

Я проверил решение в отмеченном ответе, и оно работает с простым объектом. Но на самом деле, как и в моем случае, если у вас есть вложенные объекты (объекты внутри объекта), это не работает, и я нашел термин «глубокое копирование» в эта ссылка , который отлично работает для меня.

Ответы [ 3 ]

0 голосов
/ 08 апреля 2020

Свойства объекта передаются по ссылке в Javascript. Смотрите здесь для более подробной информации. Тем не менее, доступ к наблюдаемому с использованием getValue() не так элегантен. Вы можете подписаться на получение значения без изменения источника.

Сервис

theRuleSbj = new BehaviorSubject<Rule>(null);
ruleObs = this.theRuleSbj.asObservable();

Компонент

this.ruleService.ruleObs.subscribe(rule => { this.rule = rule });
0 голосов
/ 10 апреля 2020

Чтобы вытолкнуть ваше значение из Subject, создайте из него Observable и subscribe.

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

Вы можете сделать это с помощью Синтаксис распространения .

Затем вы можете присвоить любые значения локальному объекту, которые вам нравятся, без влияния на Subject.

* 1014. * напр. ( StackBlitz )
    const theRuleSbj = new BehaviorSubject<Rule>(null);
    const theRule$ = theRuleSbj .asObservable(); 

    // The observable will emit null on the initial subscription
    // Subject minght be a better fit
    theRule$.subscribe(rule => {
        console.log(`Subscription value:`, rule);
        // Use object spread to create a new object for your component
        this.rule = { ...rule };
      });

    // Update the Subject, it will console log new value
    // and update your local value0
    theRuleSbj.next({ name: 'Name 1'});

    // Update your local value, does not effect your Subject value
    this.rule.name = 'Name 2'; 

    // Confirm that they are differant
    console.log(`Subject Value:`, theRuleSbj.getValue());
    console.log(`Local Value`, this.rule);

    // Be careful as when you update the Subject, your local value will be updated
    theRuleSbj.next({ name: 'Name 3'});
    console.log(`Subject Value (after subject update):`, theRuleSbj.getValue());
    console.log(`Local Value (after subject update)`, this.rule);

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

Если вам нужно только одно значение в компоненте, вы можете pipe() observable и использовать take(1), чтобы получить одно значение, но при инициализации Subject как BehaviourSubject, вы получите только значение null. Возможно, вы захотите изменить это значение на Subject, поэтому, когда первое значение передается на Subject, ваш компонент получает его.


    const theRuleSbj = new Subject<Rule>();

    /* other code omitted  */

    theRule$
        .pipe(take(1))
        .subscribe(rule => {
            console.log(`Subscription value:`, rule);
            this.rule = { ...rule };
        });

0 голосов
/ 08 апреля 2020

Это потому, что BehaviorSubject возвращает вам ссылку на его текущее значение. Когда вы делаете что-то вроде

this.rule.name = 'name';

, значение свойства объекта изменяется, но ссылка для всех остается неизменной. Если вам нужно локально изменить значение правила, попробуйте

this.rule = {...this.rule, {name: name}}

, оно переопределяет вашу локальную ссылку без изменения исходного значения

...