订阅推送通知服务后添加管道

时间:2019-06-07 19:31:45

标签: typescript rxjs rxjs-pipeable-operators rxjs-subscriptions

情况:
我遇到了rxjs Observable系统的用例,在其中,我可能需要在pipe启动后向Subscription添加Subscription d命令。

就我而言,我正在处理的应用程序必须被动地监听推送通知系统。可以在此系统上推送许多消息,我的系统需要对此消息做出响应。 但是,在可预见的情况下,将来将要实现的动态加载视图将需要在推送通知系统中添加侦听器。

问题:
假设我的应用处于我的.subscribe(() => {})已经存在的状态,是否可以在调用// this.something is an Observable<any>, for discussion purposes. const subscription = this.something.subscribe(() => { // commands }); this.something.pipe( map((something) => { // ...Commands that I want to add to the subscription... }) ); 之后添加其他管道?

foo_DEV

...如果我这样做,那会发生什么,如果有的话?

解决方案:
@ user2216584和@SerejaBogolubov的两个答案都回答了这个问题。

我的高级推送通知侦听器服务需要做两件事:

  1. 保留订阅,然后
  2. 能够从听众列表中提取内容。

复杂的是每个侦听器都需要侦听不同的消息。换句话说,如果我在bar_DEV上收到消息,则应用程序需要做的事情与推送通知系统在export interface PushNotificationListener { name: string, onMessageReceived: (msg: PushNotificationMessage) => any, messageSubject$: Subject<PushNotificationMessage> } export class PushNotificationListenerService { private connection$: Observable<PushNotificationConnection>; private subscription$: Subscription; private listeners: PushNotificationListener[] = []; constructor( private connectionManager: PushNotificationConnectionManager ) { } connect() { // Step 1 - Open the socket connection! this.connection$ = this.connectionManager.connect( // The arguments for setting up the websocket are unimportant here. // The underlying implementation is similarly unimportant. ); } setListener( name: string, onMessageReceived: (msg: PushNotificationMessage) => any ) { // Step 3...or maybe 2...(shrug)... // Set listeners that the subscription to the high-order connection // will employ. const newListener: PushNotificationListener = { name: name, onMessageReceived: onMessageReceived, messageSubject$: null }; this.listeners.push(newListener); } listen() { // Step 2 - Listen for changes to the high-order connection observable. this.subscription$ = this.connection$ .subscribe((connection: PushNotificationConnection) => { console.info('Push notification connection established'); for (let listener of this.listeners) { listener.messageSubject$ = connection.subscribe(listener.name); listener.messageSubject$.subscribe((message: PushNotificationMessage) => { listener.onMessageReceived(message); } } }, (error: any) => { console.warn('Push notification connection error', error); } } } 上推送消息的事情有所不同。

所以,这是我想出的:

Observable

通过仔细研究构成推送通知系统核心的内部代码,我发现我们已经有了一个高阶connectionManager.connect()。 websocket代码创建了一个可观察的(subscribe),需要将其缓存在服务中并进行订阅。由于该代码特定于我的工作地点,因此不再赘述。

但是,缓存侦听器也很重要!每当连接更改状态时,.listen()中的.addListener()调用都会遍历所有连接的侦听器,因此我可以通过Observable临时添加侦听器,这是因为rxjs的{{1 }}系统固有地起作用,并且事实上,我是在一个范围内的侦听器列表中工作的,所以我有一个系统可以动态设置侦听器,即使调用了.connect()在配置任何侦听器之前。

此代码可能仍然可以从重新设计/重构中受益,但是我有一些可行的方法,这是任何好的编码的重要第一步。谢谢大家!

2 个答案:

答案 0 :(得分:3)

[我正在编辑我的答案,因为先前的答案是根据作者共享的第一个代码;如评论中所述,作者已更改/更正了代码]-

我怀疑以下代码是否会影响订阅中的任何内容-

this.something.pipe(
  map((something) => {
    // ...Commands that I want to add to the subscription...
  })
);

您可以在最初设置可观察的对象时尝试使用高阶函数,如果高阶函数在范围内,则可以重新分配它。我还怀疑它是否可以工作,原因如下-

  1. 设置Observable时,observable保留传递的函数的引用,该函数将在订阅[{https://medium.com/@benlesh/learning-observable-by-building-observable-d5da57405d87]]上调用。现在,如果您重新分配高阶函数,那么可观察函数仍然指向旧参考。通过重新分配高阶函数,您没有更改最初设置可观察对象时设置的原始函数引用。

  2. 假定由于某种原因,高阶重新分配有效,在这种情况下,也很有可能在执行旧的高阶函数之前,您可能已经重新分配了高阶函数(因为如果源可观察到异步调用后端,在等待代码时,javascript事件循环可能已重新分配了高阶函数,当异步调用返回时,它将执行新分配的高阶函数。也许这段代码会阐明我的观点-

让highOrderFunc = map(x => x * 2);

this.something
    .pipe(
          mergeMap(_ => //call to backend; async call),
          higherOrderFunc,
         ).subscribe();
higherOrderFunc = map(x => x * 3); // this will execute before async call completes

答案 1 :(得分:2)

好吧,您可以轻松完成。假设您想要一些延迟运行的map。比起map(this.myMapper)来说,myMapper是在适当范围内可见的私有字段。通过更改该私有字段,您可以添加/删除其他行为。例如,map(x => x)表示没有任何映射。

但是,在我看来,您正在滥用rxjs。最有可能您真正需要的是高阶可观察的(发出可观察的“流”的可观察的)。那将是更rxjs更干净的解决方案。所以请三思。