gpt4 book ai didi

angular - 为什么组合的可观察对象在使用 Subject 时不更新模板,或者如果它们在 ngAfterContentInit 之后发出

转载 作者:太空狗 更新时间:2023-10-29 17:32:42 26 4
gpt4 key购买 nike

我在组件中定义了一个可观察对象 (result$),并通过异步管道将其显示在其模板上。 observable 是其他 2 个 observables(first$,second$)通过 combineLatest 的组合。如果一个或两个可观察对象发射得太早(在我发现的 ngAfterContentInit 之前),生成的可观察对象将不会发射值。

组件:不工作

@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {

result$: Observable<number>;
first$ = new Subject<number>();
second$ = new Subject<number>();

constructor() {}

ngOnInit(){
this.result$ = combineLatest(
this.first$,
this.second$
).pipe(
map(([first, second]) => {
// This is not printed to the console
console.log('combined obs emitted value');
return first + second;
})
);
console.log('first and second emit value');
this.first$.next(2);
this.second$.next(4);
}

ngAfterContentInit() {
console.log('ngAfterContentInit');
}
}

执行顺序是:

1.第一个和第二个发射值

2.ngAfterContentInit

我这里的假设是在 ngAfterViewInit 中模板已经被渲染并且订阅已经完成。因为可观察对象在此之前发出一个值,所以不会通知组件。这只能意味着生成的可观察对象是冷的(因此,您需要在它发出值之前订阅)。 2个可观察对象是主题,所以我的假设是主题是冷可观察对象。这是正确的吗?

如果我延迟发出 first$ 和 second$,一切正常:组件:first$ 和 second$ 稍后发出 @成分({ 选择器:“我的应用程序”, templateUrl: './app.component.html', styleUrls: [ './app.component.css' ] }) 导出类 AppComponent {

result$: Observable<number>;
first$ = new Subject<number>();
second$ = new Subject<number>();

constructor() {}

ngOnInit(){

this.result$ = combineLatest(
this.first$,
this.second$
).pipe(
map(([first, second]) => {
console.log('combined obs emitted value');
return first + second;
})
);

// Solution 1: add timeout
setTimeout(() => {
console.log('first and second emit value');
this.first$.next(2);
this.second$.next(4);
})

}

ngAfterContentInit() {
console.log('ngAfterContentInit');
}
}

现在的顺序是:

  1. ngAfterContentInit

  2. 第一个和第二个发射值

  3. 组合 obs 发射值

再一次,这是因为订阅是在可观察对象发出值之前进行的吗?

如果我将可观察对象更改为 BehaviorSubject,即使值在订阅发生之前发出,一切也会正常进行。这是否意味着 BehaviourSubjects 是热可观察对象?组件:作品

@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {

result$: Observable<number>;
first$ = new BehaviorSubject<number>(0);
second$ = new BehaviorSubject<number>(0);

constructor() {

}

ngOnInit(){

this.result$ = combineLatest(
this.first$,
this.second$
).pipe(
map(([first, second]) => {
// This is not printed to the console
console.log('combined obs emitted value');
return first + second;
})
);


console.log('first and second emit value');
this.first$.next(2);
this.second$.next(4);


}

ngAfterContentInit() {
console.log('ngAfterContentInit');
}
}

Stackblitz

最佳答案

Q1:2 个 observables 是 Subjects,所以我的假设是 subjects 是冷的 observables。这是正确的吗?

A1:answer from this question说这个话题本身很火。这article描述热、冷和主题。

问题 2:那么,这是不是因为订阅是在可观察对象发出值之前进行的?

A2:是的。订阅 Subject 将在您订阅后收到值。您引入的 delay() 应该为发生这种情况提供了时间。

为什么? 这是因为 BehaviorSubject 总是保存一个值并在订阅时发出它,而 Subject 不保存值,它只是将值从生产者发送到当前订阅者。 Details .

Q3:这是否意味着 BehaviourSubjects 是热可观察对象?

答:见 A1。

如果这不能直接回答您的问题,我们深表歉意。我只是想说...在处理 Subject 和 BehaviorSubject 时,我真的不在乎它们是热的还是冷的。

相反,我会问:“我是否希望可观察对象在我订阅时始终保持一个值?”。如果是,我使用 BehaviorSubject。如果我同意订阅时没有任何值(value),那么 Subject 就可以。除了这个区别,它们都将在订阅后收到发出的值。 --- 取决于您的用例。

关于angular - 为什么组合的可观察对象在使用 Subject 时不更新模板,或者如果它们在 ngAfterContentInit 之后发出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54564804/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com