RxJs。结合最新和一次

时间:2016-11-02 11:02:39

标签: rxjs rxjs5

我有这样的用户界面:

enter image description here

我可以

  • 在搜索框中输入内容
  • 将用户从表拖到图表

所需的逻辑是:

  • 最初的图表显示了所有用户的一些子集(例如,前10个)
  • 当用户被拖动到图表上时,他们会被添加到已经存在的用户
  • 当应用过滤器时,所有用户都将从图表中删除,然后使用匹配用户的某个子集重新填充

我正在尝试用RxJs实现这样的逻辑。 我有filteredUsers$addedUsers$流,可以相应地生成匹配过滤器和拖动用户的用户。

我需要以这种方式组合它们:

        Observable
            .<OPERATOR>(filteredUsers$, addedUsers$)
            .subscribe(([filteredUsers, addedUsers]) => {
                // When filteredUsers$ fires:
                //   filteredUsers is value from stream
                //   addedUsers == null

                // When addedUsers$ fires:
                //   filteredUsers is latest available value
                //   addedUsers is value from stream

                redrawChart(/* combining users */)
            });

我是如何实现这一目标的?

时间顺序:

Filtered: -  a  -  -  -  -  a  -  ->
Added   : -  -  b  -  b  -  -  -  ->
Result  : -  a  ab -  ab -  a  -  ->

3 个答案:

答案 0 :(得分:2)

如果您希望仅在addUsers $ fires with latest from时才能填充最终流:

enter image description here

因此,在您的情况下,addUsers $可能是第一个流。 您可以尝试以下代码:

from matplotlib import pyplot as plt
import subprocess, os

def plot_as_emf(figure, **kwargs):
    inkscape_path = kwargs.get('inkscape', "C://Program Files//Inkscape//inkscape.exe")
    filepath = kwargs.get('filename', None)

    if filepath is not None:
        path, filename = os.path.split(filepath)
        filename, extension = os.path.splitext(filename)

        svg_filepath = os.path.join(path, filename+'.svg')
        emf_filepath = os.path.join(path, filename+'.emf')

        figure.savefig(svg_filepath, format='svg')

        subprocess.call([inkscape_path, svg_filepath, '--export-emf', emf_filepath])
        os.remove(svg_filepath)

第一个observable每隔50毫秒发出一个数组值。 第二个可观测值每75毫秒。

打印的值为{a:2,b:5} {a:3,b:6} {a:4,b:6}

因为在5之前发出1我们失去了对(1,5)!

我不清楚但是如果没有发出其他流,则从addUsers $中丢失一对可能是您不希望的行为。 如果您使用初始值启动第二个流,然后过滤掉您不想要的任何结果,则可以克服这个问题。

答案 1 :(得分:1)

你有combineLatest运算符,基本上可以完成你所描述的内容。它结合了两个可观察量,并为您提供两个流的最新值。

所以:

- 一个 - B ----- ---Ç -x ----- ----- d P- -combineLatest- --a - B-B --- C-C   x x d d p

如果我理解正确,这可以让你做你想做的事。

这是官方文档链接: https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/combinelatest.md

答案 2 :(得分:1)

最后我通过添加其他主题来完成:

var filteredUsers$ = ... // users from filter
var addedUsers$ = ... // users dragged on chart
var usersToDraw$ = new Subject();

订阅:

usersToDraw$
    .subscribe(usersToDraw => {
        redrawChart(usersToDraw);
    });

filteredUsers$
    .subscribe(filteredUsers => {
        usersToDraw$.next(filteredUsers);
    });

Observable
    .combineLatest(filteredUsers$, addedUsers$)
    .filter(([filteredUsers, addedUsers]) => addedUsers != null)
    .subscribe(([filteredUsers, addedUsers]) => {
        // we 'clear' stream so the same users won't be added twice 
        addedUsers$.next(null);

        usersToDraw$.next(/* combining users */);
    });

<强>更新

可以使用withLatestFrom(感谢@nova)

来改进解决方案
usersToDraw$
    .subscribe(usersToDraw => {
        redrawChart(usersToDraw);
    });

filteredUsers$
    .subscribe(filteredUsers => {
        usersToDraw$.next(filteredUsers);
    });

addedUsers$
    .withLatestFrom(filteredUsers$)
    .subscribe(([addedUsers, filteredUsers]) => {
        usersToDraw$.next(/* combining users */);
    });