2017-07-14 84 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

相關問題