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