根据其他可观察对象的最近过去消息进行过滤

时间:2018-10-22 08:50:55

标签: angular rxjs reactive

我正在尝试根据另一个可观察对象的消息过滤出可观察对象之外的消息。

navCmds          --A----B---C--A------D-----------------C-----D----E--->

navNotifications ----A----X---B-C-A---D------------------------DCA---E->

result           ---------X--------------------------------------A----->

在我的程序中,我将导航命令发送到外部应用程序。
该应用程序通知我它更改为什么屏幕。
通知可能是因为我发送了导航命令,也可能是因为用户在应用程序本身中进行了导航。
我想只使用不是我发送的消息的导航命令来获得流。

由于其他应用程序不在我的控制范围内,因此无法使用相关ID或其他新字段扩展消息。

我想解决这个问题的方式

  • 在navCmds上创建窗口
  • 在最新窗口中过滤navNotifications

不是对命令的直接响应但在窗口中早些时候作为cmd发送的通知将丢失。 这是可以接受的折衷方案。

const notificationsStopped$ = this.navCmds$.pipe(debounceTime(500));
const cmdWindows$ = this.navCmds$.pipe(windowOperator(notificationsStopped$));

const result$ = this.navNotifications$.pipe(
    withLatestFrom(cmdWindows$),
    filter(([notification, pastCmds$]) => // How to filter here?)
);      

有没有更简单的方法?
我该如何过滤?

2 个答案:

答案 0 :(得分:1)

要用navNotifications过滤navCmds-我们要用navCmds收集所有scan

  

扫描-随着时间的推移而减少。

我们假设pastCmd可序列化以放入对象。也可以使用Map,因为它可以将引用用作键

const allPastCmds$ = pastCmds$.pipe(scan(acc, cur)=>({...acc, [cur]: true}),{});

notificationExist检查notification中的allPastCmds

filter(([notification, allPastCmds]) => !notificationExist(notification, allPastCmds)

答案 1 :(得分:1)

如果我正确理解了您的问题,则将对您为问题提出的大理石图进行一些更改。

尤其是,我会将DCA的最后一个navNotifications序列更改为CDA,以反映以下事实:在navCmds序列中,首先发送{{1 }},然后C。这意味着大理石图看起来像这样

D

假设这是正确的,必须加以确认,您可以按照以下思路考虑解决方案

navCmds          --A----B---C--A------D-----------------C-----D----E--->

navNotifications ----A----X---B-C-A---D------------------------CDA---E->

result           ---------X--------------------------------------A----->

这里的想法是

  • 首先创建一个const queue = new Array<any>(); navCmds$.pipe( tap(cmd => queue.push(cmd)), switchMap(() => { return navNotifications$.pipe( switchMap(notification => { const cmdFromQueue = queue[0]; if (notification === cmdFromQueue) { queue.shift(); return empty(); } else { return of(notification); } }) ) }) ) ,在其中存储发送的命令
  • 只要queue发出新命令,该值就会被推送 navCmds$中将流切换到queue 它检查navNotifications$并发出queue(如果是) 与上次处理的命令不同

此解决方案要求通过notification变量维护 state ,但是可以使用自定义的管道运算符将其隐藏。

这些解决方案已通过以下测试数据进行了测试

queue