Re: [問題] Angular的service在路由間觸發的問題

作者: LoveMoon (我不是魔獸三國作者.....)   2018-12-27 01:02:58
※ 引述《heavenbetula (綠草)》之銘言:
: 大家好~小弟是Angular剛接觸沒多久的新手
: 最近在使用Service在路由間跳轉時遇到一些問題
: https://stackblitz.com/edit/angular-w3njbx
: ↑上面的程式,我在child1 component中訂閱了service裡的Subject物件,
: 而在child2 component的按鈕按下後,才會接收到觸發了,而去做後續行為
: 這個例子中,我預期的就是按鈕每按一次,我就console.log一次,
: 但是我發現,在路由跳轉的過程中,只要child2 component進入一次
: 就會連同上次的紀錄都留著,也就是說:
: 第一次進入child2 component按下按鈕一次,console.log一次(正常)
: 先按連結離開child2 component
: 第二次再進入child2 compoent按下按鈕一次,console.log直接跳出兩次結果
: 先按連結離開child2 component
: 第三次再進入child2 component按下按鈕一次,console.log直接跳出三次結果
: 請問為什麼會這樣呢?
你在Child1Component中用constructor injection注入service
因為Angular的DI機制,沒特別設定Injector的話service會從component開始往上找
然後你的FooteractionService只有由AppModule做Provider
所以service的instance是singleton
每次切換路由時會建立/消滅Component
每次切換到Child1的路由時都會產生一個Child1的instance
並且每次注入的都是同一個service
訂閱的也都是同一個service裡的subject
訂閱寫在constructor裡每次Child1產生一次就訂閱一次
呼叫service.action()的時候因為之前的訂閱沒有被取消掉,
自然會重複觸發subscribe()裡面的callback
目前普遍建議的做法大概是這樣
在Child1中給一個$destroy的property = new Subject<void>();
Class implements OnDestroy
在生命週期方法內做$destroy.next()和$destroy.unsubscribe()
然後在訂閱service內subject的時候不要直接訂閱
用subject.pipe(takeUntil(this.$destroy)).subscribe()
這樣Child1因為路由變更消滅後
訂閱的subject發送時就不會觸發該次的subscribe()裡面的callback
如果上面的原理看不懂的話就抄最後的程式碼就好了
但是如果要繼續玩Angular甚至拿它來做大專案
還是要了解一下他的routing跟DI 還有RxJS的原理以及operators
這樣過程會比較愉快一點
作者: heavenbetula (綠草)   2018-12-27 21:19:00
謝謝你的回文!!雖然我還是看不太懂...不過也有爬文說設置一個Subscription型別的屬性讓這個屬性=subscribe的callback我直接在原文打好了比較好理解XD
作者: LoveMoon (我不是魔獸三國作者.....)   2018-12-27 22:55:00
另外就是 英文起碼要練好閱讀能力如果你想成長的比較順利的話如果有時間的話我會在blog寫observer patter的介紹真的有寫出來再把連結貼給你
作者: heavenbetula (綠草)   2018-12-28 12:59:00
謝謝其實我是takeUntil那邊沒用過不知道

Links booklink

Contact Us: admin [ a t ] ucptt.com