作者LoveMoon (我不是魔獸三國作者.....)
標題Re: [問題] Angular的service在路由間觸發的問題
時間Thu Dec 27 01:02:58 2018
※ 引述《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
這樣過程會比較愉快一點
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 123.240.48.162
※ 文章網址: https://www.ptt.cc/bbs/Web_Design/M.1545843781.A.ED8.html
※ 編輯: LoveMoon (123.240.48.162), 12/27/2018 01:14:14
推 heavenbetula: 謝謝你的回文!!雖然我還是看不太懂... 12/27 21:19
→ heavenbetula: 不過也有爬文說設置一個Subscription型別的屬性 12/27 21:21
→ heavenbetula: 讓這個屬性=subscribe的callback 12/27 21:23
→ heavenbetula: 我直接在原文打好了比較好理解XD 12/27 21:24
不知道你的看不懂是指哪邊
如果是routing跟component的關係,你需要了解routing
如果是component跟construction injection的關係,你需要了解DI
如果是重複訂閱的問題,你需要了解observer pattern和RxJS
不了解Angular和RxJS我覺得沒什麼
但是你需要能夠從關鍵字去延伸閱讀相關的知識和文件
下面文章
第一篇是takeUntil vs. Subscription.unsubscribe
第二篇是使用takeUntil時需要注意的地方
請你自己閱讀
https://medium.com/@benlesh/rxjs-dont-unsubscribe-6753ed4fda87
https://blog.angularindepth.com/rxjs-avoiding-takeuntil-leaks-fb5182d047ef
※ 編輯: LoveMoon (123.240.48.162), 12/27/2018 22:51:11
→ LoveMoon: 另外就是 英文起碼要練好閱讀能力 12/27 22:55
→ LoveMoon: 如果你想成長的比較順利的話 12/27 22:55
→ LoveMoon: 如果有時間的話我會在blog寫observer patter的介紹 12/27 22:58
→ LoveMoon: 真的有寫出來再把連結貼給你 12/27 22:59
推 heavenbetula: 謝謝其實我是takeUntil那邊沒用過不知道 12/28 12:59