当最后一位主题观察者取消订阅该主题时,AsyncSubject
变为可观察的。这是the quote:
一旦完成,就完成了。受试者在他们之后不能重复使用 取消订阅,已完成或已出错。
以下是演示:
const ofObservable = Rx.Observable.of(1, 2, 3);
const subject = new Rx.AsyncSubject();
ofObservable.subscribe(subject);
subject.subscribe((v) => {
console.log(v);
});
subject.unsubscribe((v) => {
console.log(v);
});
// here I'll get the error "object unsubscribed"
subject.subscribe((v) => {
console.log(v);
});
如何防止主题完成?
有share
运算符:
在RxJS 5中,运算符
share()
生成一个热的refCounted observable 可以在失败时重试,也可以在成功时重复。因为 受试者一旦出错,完成或以其他方式不能重复使用 取消订阅后,share()
运营商会将已发布的主题回收 启用重新订阅以生成observable。
这就是我要找的东西。但share
创建了一个主题,我需要AsyncSubject
。
答案 0 :(得分:8)
问题出在这一行:
subject.unsubscribe((v) => {
console.log(v);
});
Subject
implements ISubscription
;这意味着它具有unsubscribe
方法和closed
属性。它的implementation of unsubscribe
如下:
unsubscribe() {
this.isStopped = true;
this.closed = true;
this.observers = null;
}
这有些残酷。从本质上讲,它会切断与主题的任何订阅者的所有通信,而不会取消订阅。同样,它也不会取消订阅主题本身,也不会取消订阅可能发生的任何观察。 (它还将主题标记为已关闭/已停止,这是您出错的原因。)
鉴于它没有实际执行任何取消订阅,它应该如何使用尚不清楚。 this test:
的说明it('should disallow new subscriber once subject has been disposed', () => {
表明它可能是某种来自RxJS 4的宿醉 - 其中取消订阅被称为处置。
不管它存在的原因是什么,我建议永远不要叫它。举例来说,请看这个片段:
const source = Rx.Observable
.interval(200)
.take(5)
.do(value => console.log(`source: ${value}`));
const subject = new Rx.Subject();
source.subscribe(subject);
const subscription = subject
.switchMap(() => Rx.Observable
.interval(200)
.take(5)
.delay(500))
.subscribe(value => console.log(`subscription: ${value}`));

.as-console-wrapper { max-height: 100% !important; top: 0; }

<script src="https://unpkg.com/rxjs@5/bundles/Rx.min.js"></script>
&#13;
它将主题订阅到源可观察对象,然后订阅由该主题组成的可观察对象。
如果在主题上调用unsubscribe
,则会出现一些问题:
next
方法时会产生错误;和interval
switchMap
unsubscribe
中的const source = Rx.Observable
.interval(200)
.take(5)
.do(value => console.log(`source: ${value}`));
const subject = new Rx.Subject();
source.subscribe(subject);
const subscription = subject
.switchMap(() => Rx.Observable
.interval(200)
.take(5)
.delay(500))
.subscribe(value => console.log(`subscription: ${value}`));
setTimeout(() => {
console.log("subject.unsubscribe()");
subject.unsubscribe();
}, 700);
观察点会在.as-console-wrapper { max-height: 100% !important; top: 0; }
来电后不断发出。尝试一下:
<script src="https://unpkg.com/rxjs@5/bundles/Rx.min.js"></script>
&#13;
unsubscribe
&#13;
Subject
&#13;
这似乎都不是理想的行为,因此在Subscription
上调用subscribe
是值得避免的。
相反,代码段中的代码应使用const subscription = subject.subscribe((v) => {
console.log(v);
});
subscription.unsubscribe();
调用返回的next
取消订阅:
unsubscribe
在写完这个答案之后,我发现了来自following comment的Ben Lesh,这符合我的理论,它与处理该主题有关:
如果您希望主题在
<div id="modal" style="background-color: #000;"> <!--MODAL----> <span id="close">×</span> </div> <img id="image" src="agave.jpg"/> <!--Click to display modal-->
完成后对其进行大声和愤怒的错误,您可以直接在主题实例上调用var img = document.getElementById("image"); function displayModal(event){ var modal = document.getElementById("modal"); if(modal.style.display == "none"){ modal.style.display = "block"; } else{modal.style.display = "none";} } img.addEventListener("click", displayModal(event));
。