组合数组流和单值

时间:2017-12-08 14:20:35

标签: rxjs

我有一个场景我想帮助弄清楚如何在rxjs中实现它。

来源可观测量:

  • single:使用id字段发出单个值
  • many:发出与single
  • 相同类型的值数组

流要求:

概述:流的最终结果是一个值数组,表示many发出的最新值,由single上一次发出后many发出的值覆盖。< / p>

  • many至少发出一次
  • 之前不会发出任何内容
  • single发出的值会累积并覆盖many
  • 先前发出的相应值(按ID)
  • many发出累积的single值时会被清除

实际情景:

我有一个可过滤的数据表组件,它有子组件,代表每列的每个过滤器。与每列(many)对应的过滤器设置列表可以从其父列表下推到组件中。子过滤器组件可以为自己发出过滤器更改(single)。父组件的设置优先于子过滤器组件。

我尝试过什么

console.clear();
const many = Rx.Observable.create(o => {
  setTimeout(() => {
    o.next([
      { id: 1, value: 'a' },
      { id: 2, value: 'b' },
      { id: 3, value: 'c' }
    ]);
  }, 1000);
  setTimeout(() => {
    o.next([
      { id: 1, value: 'x' },
      { id: 2, value: 'y' },
      { id: 3, value: 'z' }
    ]);
  }, 4000);
});

const single = Rx.Observable.create(o => {
  o.next({ id: 1, value: 'd' });
  setTimeout(() => { o.next({ id: 2, value: 'e' }); }, 2000);
  setTimeout(() => { o.next({ id: 3, value: 'f' }); }, 3000);
  setTimeout(() => { o.next({ id: 1, value: 'g' }); }, 5000);
});

single
  .scan((acc, x) => {
    return [...acc.filter(y => y.id !== x.id), x];
  }, [])
  .startWith([])
  .combineLatest(many)
  .map(x => {
    const s = x[0];
    const m = x[1];
    return [...m.filter(y => !s.some(z => z.id === y.id)), s];
  })
  .subscribe(x => { console.log(JSON.stringify(x)); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.5/Rx.min.js"></script>

single发出时,此代码不会重置累积的many值。

问题

如何在rxjs中实现上述场景?

修改

我找到了一个解决方案(发布在下面),但我会接受更好的实施。谢谢!

1 个答案:

答案 0 :(得分:0)

Blaaah ......发布后我很快意识到我做错了什么。我只需要颠倒顺序。这是我的解决方案,但我愿意接受更好的选择。

&#13;
&#13;
const many = new Rx.Subject();
const single = new Rx.Subject();

// create the stream
const stream = many
  .switchMap(m => {
    return single
      .scan((acc, x) => {
        return [...acc.filter(y => y.id !== x.id), x];
      }, [])
      .startWith([])
      .map(s => {
        return [...m.filter(y => !s.some(z => z.id === y.id)), ...s];
      });
  })
  .subscribe(x => { console.log(JSON.stringify(x)); });

// send the data
single.next({ id: 1, value: 'd' });
setTimeout(() => {
  many.next([
    { id: 1, value: 'a' },
    { id: 2, value: 'b' },
    { id: 3, value: 'c' }
  ]);
}, 1000);
setTimeout(() => { single.next({ id: 2, value: 'e' }); }, 2000);
setTimeout(() => { single.next({ id: 3, value: 'f' }); }, 3000);
setTimeout(() => {
  many.next([
    { id: 1, value: 'x' },
    { id: 2, value: 'y' },
    { id: 3, value: 'z' }
  ]);
}, 4000);
setTimeout(() => { single.next({ id: 1, value: 'g' }); }, 5000);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.5/Rx.min.js"></script>
&#13;
&#13;
&#13;