【问题标题】:There's a way of create this sequence of Streams?有一种方法可以创建这个 Streams 序列吗?
【发布时间】:2016-03-21 13:34:29
【问题描述】:

我正在尝试实现这个大理石图,具有 N 个 sN$ 的 hipotesis,我正在将此流添加到 main$。

s1$    +--1--------------------99--------------------->
s2$    +------3--------7------------------------------>

main$  +---[1]-[1, 3]---[1, 7]---[99, 7]-------------->

现在我有一个近似值,但带有“重复”

const main$ = new Rx.Subject()
const s1$ = new Rx.Subject()
const s2$ = new Rx.Subject()

main$
  .scan((a, c) => [...a, c], [])
  .subscribe(v => console.log(v))

s1$.subscribe(x => main$.onNext(x))
s2$.subscribe(x => main$.onNext(x))    

s1$.onNext(3)
s2$.onNext(1)

s1$.onNext(6)
s2$.onNext(44)

/*
  Expect:
    [3]
    [3, 1]
    [6, 1]
    [6, 44]
*/

/*
  What I have:
     [3]
     [3, 1]
     [3, 1, 6]
     [3, 1, 6, 44]
*/

有办法做到这一点吗? 我还尝试将流 sN$ 添加到 main$ 中:

const main$ = new Rx.Subject()
const s1$ = new Rx.Subject()
const s2$ = new Rx.Subject()

main$
  .mergeAll()
  .scan((a, c) => [...a, c], [])
  .subscribe(
    (v) => console.log(v)
  )

main$.onNext(s1$)
main$.onNext(s2$)

s1$.onNext(3)
s2$.onNext(1)

s1$.onNext(6)
s2$.onNext(44)

【问题讨论】:

    标签: javascript rxjs observable


    【解决方案1】:

    您可以使用combineLatest。虽然这仍然要求每个流都以一个值开头,但您可以为 null 值添加前缀,以使每个流都以使用 startWith 的内容开头。

    const source = Rx.Observable.combineLatest(
      s1.startWith(void 0),
      s2.startWith(void 0),
      s3.startWith(void 0),
      (s1, s2, s3) => [s1, s2, s3])
    

    您可以选择从结果数组中删除 undefined 值。

    现在,我们可以将其扩展为使用可变的流列表。感谢@xgrommx。

    main$
     .scan((a, c) => a.concat(c), [])
     .switch(obs => Rx.Observable.combineLatest(obs))
    

    当我们switch 时,我们也可以使用c.shareReplay(1) 让流记住最后一个值。但是,它不会与c.startWith(void 0) 结合使用,因此我们可以使用其中一个。

    例子:

        const main$ = new Rx.Subject()
        const s1$ = new Rx.Subject(1)
        const s2$ = new Rx.Subject(1)
        const s3$ = new Rx.Subject(1)
        const s4$ = new Rx.Subject(1)
    
        main$
         .scan((a, c) => a.concat(c.shareReplay(1)), [])
         .map(obs => Rx.Observable.combineLatest(obs))
         .switch()
         .map(v => v.filter(e => !!e))
         .map(v => v.join(','))
         .subscribe(v => $('#result').append('<br>' + v))
    
        main$.onNext(s1$)
        s1$.onNext(1)
        main$.onNext(s2$)
        s2$.onNext(void 0) // Since we can't use startWith
        main$.onNext(s3$)
        s3$.onNext(5)
        s1$.onNext(55)
        s2$.onNext(12)
        s2$.onNext(14)
        s3$.onNext(6)
        main$.onNext(s4$)
        s4$.onNext(999)
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.6/rx.all.js"></script>
        <div id="result"></div>

    【讨论】:

      【解决方案2】:

      我最终解决了一些问题,过滤了我在startWith() 开始的空值:

      main$
        .scan((a, c) => [...a, c.startWith(null).shareReplay(1)], [])
        .map(obs => Observable.combineLatest(obs))
        .switch()
        .map((x) => x.filter((x) => x != null))
        .filter((x) => x.length)
      

      看起来不可读(就像任何 Rx 序列一样,但如果你画弹珠就完全有意义!)

      【讨论】:

      • 你为什么使用“startWith”?
      • 也许你可以使用像js main$ .scan((a, c) =&gt; [...a, c.startWith(null).shareReplay(1)], []) .map(obs =&gt; Rx.Observable.combineLatest(obs).map(x =&gt; x.filter(Boolean)).filter(x =&gt; x.length)) .switch() 这样的smth
      • 为数组中的当前主题设置一些值,以便能够将Latest与某些东西结合起来(在这种情况下为空)。有意义吗?
      • 是的,但是 for 只是在流上移动功能操作,并且在切换后过滤对我来说更有意义。
      猜你喜欢
      • 2022-11-18
      • 2019-10-12
      • 1970-01-01
      • 2014-01-09
      • 2014-08-02
      • 1970-01-01
      • 2023-03-03
      • 2018-09-23
      • 2013-03-08
      相关资源
      最近更新 更多