2017-07-14 69 views
2

当最后一位主题观察者取消订阅主题时,AsyncSubject变得可观察。这里是the quote如何防止在最后一位观察者取消订阅时完成AsyncSubject

完成后就完成了。受试者在 取消订阅,完成或出错后不能重新使用。

以下是演示:

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(),使一热,引用计数观察到 可以在失败重试,或重复成功。由于 受试者一旦出错,完成或以其他方式取消订阅,share()操作员将回收死亡主题为 ,从而允许重新订阅生成可观察结果。

这就是我要找的。但是share创建了一个主题,我需要AsyncSubject

+0

[This test](https://github.com/ReactiveX/rxjs/blob/5.4.2/spec/subjects/AsyncSubject-spec.ts#L125-L141)表明它应该表现出你的行为方式期待它,不是吗?其他事情还能继续吗? – cartant

+0

嗯,谢谢,检查[这个运动员](https://plnkr.co/edit/wFRWuiyWtsolP5CESdaA?p=preview),没有其他东西 –

+1

它看起来有点像打字错误,对我来说。将'subject.subscribe'调用的结果分配给一个变量(结果是订阅)并在订阅上调用'unsubscribe'而不是主题。随着这种变化,这个庞然大物似乎做到了我所期望的。 – cartant

回答

2

的问题是降低到这一行:

subject.unsubscribe((v) => { 
    console.log(v); 
}); 

Subjectimplements 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/bundles/Rx.min.js"></script>

它赞成一个受观察的源,然后从主题订阅可观察到的组成。

如果unsubscribe被称为关于这个问题,一对夫妇的问题变得很明显:

  • 对象的订阅源不是取消订阅,当源试图调用对象的next方法的误差影响;并且
  • 对由该主题组成的观察值的订阅未被取消订阅,因此switchMap内的interval可在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/bundles/Rx.min.js"></script>

的这一切似乎是可取的行为,因此呼吁在Subjectunsubscribe是要避免的东西。

相反,在你的代码段代码应该取消使用由subscribe调用返回的Subscription

const subscription = subject.subscribe((v) => { 
    console.log(v); 
}); 
subscription.unsubscribe(); 

继写这个答案,我发现从Ben Leshfollowing comment,与适合我的理论认为它与处理该主题有关:

如果你想让主体大声而愤怒地错误,当你next完成后有用,您可以直接调用unsubscribe对主题实例本身。

+0

上使用多播,非常感谢您的深入分析! –

+0

你会写关于可观察物的任何信息吗?博客也许? –

+0

最近决定开始在中等写作。我的堆栈溢出配置文件中有一个链接。 – cartant

相关问题