我不明白为什么这行不通,但是下面的替代方法行得通。
app.component.ts
import { Component } from '@angular/core';
import { Subject, Observable } from 'rxjs';
import { first } from 'rxjs/operators';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
id = 0;
obs = new Subject();
changeValue() {
this.fakeApiCall(this.id++)
.pipe(first())
.subscribe(this.obs);
}
fakeApiCall(id: number) {
return new Observable(observer => {
console.log('called with id ' + id);
observer.next({ items: [id, Math.random()] });
});
}
}
app.component.html
<h1>
<div *ngIf="(obs | async) as v">
<ul>
<li *ngFor="let item of v.items">
{{ item }}
</li>
</ul>
<ul>
<li *ngFor="let item of v.items">
{{ item }}
</li>
</ul>
</div>
<div *ngIf="(obs | async) as v">
<ul>
<li *ngFor="let item of v.items">
{{ item }}
</li>
</ul>
<ul>
<li *ngFor="let item of v.items">
{{ item }}
</li>
</ul>
</div>
<button (click)="changeValue()">increase counter</button>
</h1>
当我单击“增加计数器”按钮时,它首先获取值,但之后不获取,而这些替代方法也可以正常工作:
changeValue() {
this.fakeApiCall(this.id++)
.subscribe(this.obs)
.unsubscribe();
}
或
changeValue() {
this.fakeApiCall(this.id++)
.pipe(take(2)) // NOTES: if I write take(1), it has the same effect.
.subscribe(this.obs);
}
我很困惑,这是一个错误还是这里真正发生了什么?
编辑:如果要使用stackblitz网址,请访问:https://stackblitz.com/edit/angular-28eyiy
答案 0 :(得分:1)
这不是错误,问题出在用Subject
预订subscribe(this.obs)
的方式上。
使用subscribe(this.obs)
时,您会将所有通知传递给Subject
实例。这意味着next
,complete
和error
通知。这就是问题所在,first()
将在第一次发射后完成链(请参见Angular 2 using RxJS - take(1) vs first()),这意味着它将传递一个next
和一个complete
通知。当Subject
收到complete
通知时,它停止了,并且即使您再次订阅另一个链(这是"The Observable Contract"的一部分)也永远不会重新发送任何东西。
因此,如果您想在多个订阅中使用相同的Subject
,而您知道它们将完成,则只能传递next
通知,仅此而已(Subject
将保持活动状态) :
.subscribe(v => this.obs.next(v));