作者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://webptt.com/cn.aspx?n=bbs/Web_Design/M.1545843781.A.ED8.html
※ 编辑: LoveMoon (123.240.48.162), 12/27/2018 01:14:14
1F:推 heavenbetula: 谢谢你的回文!!虽然我还是看不太懂... 12/27 21:19
2F:→ heavenbetula: 不过也有爬文说设置一个Subscription型别的属性 12/27 21:21
3F:→ heavenbetula: 让这个属性=subscribe的callback 12/27 21:23
4F:→ 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
5F:→ LoveMoon: 另外就是 英文起码要练好阅读能力 12/27 22:55
6F:→ LoveMoon: 如果你想成长的比较顺利的话 12/27 22:55
7F:→ LoveMoon: 如果有时间的话我会在blog写observer patter的介绍 12/27 22:58
8F:→ LoveMoon: 真的有写出来再把连结贴给你 12/27 22:59
9F:推 heavenbetula: 谢谢其实我是takeUntil那边没用过不知道 12/28 12:59