所以我正在通过构建以下沙箱来试验 ngrx 和 ngrx/effects:
https://stackblitz.com/edit/ngrx-vanilla
快速介绍:
- 它在 app/store 中有一个根商店
- 它延迟加载了 app/features 中的两个模块
- 它在 app/commons 中有单例服务
三页:
- 行动项目:路由到此页面会触发随机生成三个愚蠢的公司行动项目
- 用户:基本掌握 > 详细了解 redux 实现和路由器支持
- meeting:提出问题的地方,点击“开始meeting”,见证相关的思想交流。
问题和上下文:
- 我了解 redux 中的所有数据更新都是通过操作进行的
- “effects”库用于处理异步事件,以便根据第 3 方事件和异步调用分派(dispatch)新操作。
- app/common/meeting/service 模仿例如 websocket 或 firebase 实时数据库推送更新的行为。
收到更新后(如 app/store/effects/meeting.effects.ts 所示),将调度新的操作。
最后,问题是:让公共(public)服务了解商店是否是一种干净的做法?将监听器注册到 websocket/firebase 实时数据库以便在推送数据时调度操作的最佳位置在哪里?
在这里,我这样做是为了让一个效果 (meeting.effects) 对 meetingActions.START_MEETING 操作类型使用react,并且每当推送数据时,都会向商店发送一个更新订单,但由于我来的一系列原因,这感觉不对与:
- 难以单独进行单元测试(需要比自身更多的上下文)
- 在“停止 session ”操作的情况下,此方法需要存储订阅(或?)以停止订阅。在我的方法中,无法控制在荒野中创建的可观察对象。
通常如何处理此类案件?
最佳答案
假设 websocket
发出不同类型的事件,将每个事件映射到 websocket
服务中的不同操作,例如
@Injectable()
class WebsocketService{
private socket$:Observable<Action>
getActions():Observable<Action>{
if(!this.socket$) {
this.socket$ = Observable.webSocket(url).pipe(
map(functionToMapActions)
,shareReplay(1)
);
}
return this.socket$;
}
}
其中 functionToMapActions
将 webSocket 事件映射到操作,我建议添加 shareReplay
运算符,这样我们只读取一次 webSocket。
Observable.webSocket
连接到 webSocket,并在事件到达时发出事件
当您订阅webService.getActions()
可以在@Effects
初始化中订阅websocket Action see here
@Effect()
init$ = this.websocketService.getActions();
一旦您的应用程序启动(如果效果在根模块中)或您的模块加载(如果它在延迟加载模块中),这将发出所有操作;
或者如果您对一组有限的操作感兴趣,您可以这样做
@Effect()
init$ = this.websocketService.getActions().pipe(filter(filterNeededActionsHere));
你也可以只在像这样的特定事件之后开始监听 Action
@Effect()
init$ = this.actions$.pipe(
ofType('Event which marks start')
,swichMapTo(this.websocketService.getActions())
);
和前面的例子一样,你也可以像以前一样过滤掉这里的 Action
希望这能回答你的问题
关于angular - 关于这个 Angular + ngRx(效果)的建议 - websocket 事件呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49076492/