RxJS交错合并的可观察量(优先级队列?)

时间:2018-02-10 17:05:08

标签: merge observable priority-queue rxjs5 reactive

更新

我想我已经找到了解决方案。我在这个视频中解释它。基本上,使用timeoutWith,以及一些带zip的技巧(在zip中)。

https://youtu.be/0A7C1oJSJDk

如果我有一个这样的观察者:

A-1-2--B-3-4-5-C--D--6-7-E

我想把"数字"优先级较低;它应该等到"字母"填充(例如一组2)或达到超时,然后它可以发出。也许以下插图(所需结果)可以提供帮助:

A------B-1-----C--D-2----E-3-4-5-6-7

我一直在尝试一些想法......其中之一:第一步是拆分流(groupBy),一个包含字母,另一个包含数字......,然后"某事在中间"发生......,最后这两个(子)流合并。

这是"中间的东西"我想弄清楚的是什么。

如何实现呢? RxJS(版本5.5.6)甚至可以实现这一点吗?如果不是,最接近的是什么?我的意思是,我想要避免的是拥有"数字"淹没了溪流,没有给“"字母”提供足够的机会。及时处理。

到目前为止,我所做的这段视频可能也可以澄清:

到目前为止,我的解决方案存在的问题(使用.delay延迟"数字"子流)的每个发射都不是最理想的,因为它甚至在"字符之后仍保持慢速(10秒)的时钟。 #34; (子)流已经结束(没有完成 - 这里没有明确的边界 - 只是没有为不确定的时间量获得更多的价值)。我真正需要的是拥有"数字"一旦发生这种情况,子流就会加快步伐(到2秒)。

2 个答案:

答案 0 :(得分:0)

关键在于使用timeoutWith,切换到更具侵略性的"起搏器"当"事件"踢进去。在这种情况下,"事件"在高优先级流中检测到空闲"

视频:https://youtu.be/0A7C1oJSJDk

答案 1 :(得分:0)

不幸的是,我不知道RxJs5那么多并且自己使用xstream(由RxJS5的贡献者之一创作),这在运营商数量方面稍微简单一些。

有了这个我制作了以下例子: (注意:运算符与Rx5中的运算符非常相似,主要区别在于flatten wich或多或少类似switch但似乎以不同方式处理同步流。)

const xs = require("xstream").default;

const input$ = xs.of("A",1,2,"B",3,4,5,"C","D",6,7,"E");

const initialState = { $: xs.never(), count: 0, buffer: [] };
const state$ = input$
    .fold((state, value) => {
        const t = typeof value;
        if (t === "string") {
            return {
                ...state,
                $: xs.of(value),
                count: state.count + 1
            };
        }
        if (state.count >= 2) {
            const l = state.buffer.length;
            return {
                ...state,
                $: l > 0 ? xs.of(state.buffer[0]) : xs.of(value) ,
                count: 0,
                buffer: state.buffer.slice(1).concat(value)
            };
        }
        return {
            ...state,
            $: xs.never(),
            buffer: state.buffer.concat(value),
        };
    }, initialState);


xs
    .merge(
        state$
        .map(s => s.$),
        state$
        .last()
        .map(s => xs.of.apply(xs, s.buffer))
    )
    .flatten()
    .subscribe({
        next: console.log
    });

这给了我你想要的结果。

它的工作原理是将流折叠在自身上,查看值的类型并根据它发出新的流。当你需要等待因为没有发送足够的信件时,我会发出一个empty流(没有值,没有错误,没有完成)作为"占位符"。

您可以代替发出此空流,而不是发出类似

的内容
xs.empty().endsWith(xs.periodic(timeout)).last().mapTo(value):
// stream that will emit a value only after a specified timeout.
// Because the streams are **not** flattened concurrently you can
// use this as a "pending" stream that may or may not be eventually
// consumed

其中value是最后收到的数字,以便实现与超时相关的条件,但是您需要在Rx中引入Subject或在xstream中使用xs.imitate引入某种反身性,因为您需要通知你的州你的"待定"已经消耗了流,这使得通信双向通信,而流/可观察数据是单向的。