Rxjs Behavior Subject 值更改而不调用 next
Rxjs Behavior Subject value changes without calling next
假设我的服务中有一个行为主体:
theRuleSbj = new BehaviorSubject<Rule>(null);
然后在我的组件中使用 getValue() 方法获取该值:
this.rule = this.ruleService.theRuleSbj.getValue();
然后如果我更改本地规则对象中的一些数据。例如:
this.rule.name = 'name';
我的行为主体值也变了,没调用next!似乎我的变量绑定到行为主体,所以我的局部变量的每一个变化都会影响我的行为主体。
这是主体行为行为吗!!??或者我做错了什么? (假设我在更改局部变量时不想更改行为主体)。
更新:
我测试了标记答案中的解决方案,它适用于一个简单的对象。但实际上在我的情况下,如果你有一个嵌套对象(对象内的对象),这是行不通的,我发现 this link 中的 "deep copy" 术语非常适合我。
这是因为 BehaviorSubject returns 你 link 它的当前值。当你做类似
的事情时
this.rule.name = 'name';
object 属性 值改变了,但是 link shared for everyone 还是一样的。
如果您需要在本地更改规则值,请尝试
this.rule = {...this.rule, {name: name}}
它会在不更改源值的情况下覆盖您的本地 link
对象属性在 Javascript 中通过引用传递。有关详细信息,请参阅 here。也就是说,使用 getValue()
访问可观察对象并不是那么优雅。您可以在不修改源的情况下订阅获取值。
服务
theRuleSbj = new BehaviorSubject<Rule>(null);
ruleObs = this.theRuleSbj.asObservable();
组件
this.ruleService.ruleObs.subscribe(rule => { this.rule = rule });
要将您的值从 Subject
中推出,请从中创建一个 Observable
并 subscribe
。
如果你想要值的本地版本,由于在 JavaScript 中通过引用传递对象,你需要复制一份,所以在订阅时创建一个新对象。
您可以使用 Spread Syntax 来做到这一点。
然后你可以在不影响 Subject
.
的情况下为本地对象分配任何你喜欢的值
例如(StackBlitz)
const theRuleSbj = new BehaviorSubject<Rule>(null);
const theRule$ = theRuleSbj.asObservable();
// The observable will emit null on the initial subscription
// Subject might 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 value
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 };
});
假设我的服务中有一个行为主体:
theRuleSbj = new BehaviorSubject<Rule>(null);
然后在我的组件中使用 getValue() 方法获取该值:
this.rule = this.ruleService.theRuleSbj.getValue();
然后如果我更改本地规则对象中的一些数据。例如:
this.rule.name = 'name';
我的行为主体值也变了,没调用next!似乎我的变量绑定到行为主体,所以我的局部变量的每一个变化都会影响我的行为主体。 这是主体行为行为吗!!??或者我做错了什么? (假设我在更改局部变量时不想更改行为主体)。
更新:
我测试了标记答案中的解决方案,它适用于一个简单的对象。但实际上在我的情况下,如果你有一个嵌套对象(对象内的对象),这是行不通的,我发现 this link 中的 "deep copy" 术语非常适合我。
这是因为 BehaviorSubject returns 你 link 它的当前值。当你做类似
的事情时this.rule.name = 'name';
object 属性 值改变了,但是 link shared for everyone 还是一样的。 如果您需要在本地更改规则值,请尝试
this.rule = {...this.rule, {name: name}}
它会在不更改源值的情况下覆盖您的本地 link
对象属性在 Javascript 中通过引用传递。有关详细信息,请参阅 here。也就是说,使用 getValue()
访问可观察对象并不是那么优雅。您可以在不修改源的情况下订阅获取值。
服务
theRuleSbj = new BehaviorSubject<Rule>(null);
ruleObs = this.theRuleSbj.asObservable();
组件
this.ruleService.ruleObs.subscribe(rule => { this.rule = rule });
要将您的值从 Subject
中推出,请从中创建一个 Observable
并 subscribe
。
如果你想要值的本地版本,由于在 JavaScript 中通过引用传递对象,你需要复制一份,所以在订阅时创建一个新对象。
您可以使用 Spread Syntax 来做到这一点。
然后你可以在不影响 Subject
.
例如(StackBlitz)
const theRuleSbj = new BehaviorSubject<Rule>(null);
const theRule$ = theRuleSbj.asObservable();
// The observable will emit null on the initial subscription
// Subject might 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 value
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 };
});