簡體   English   中英

如何實現RxJS flatMapLatestTwo

[英]How to implement RxJS flatMapLatestTwo

RxJS的flatMapLatest使最新的(只有一個)嵌套的Observable變平。 我有一個用例,我不想要flatMap(從過去扁平化所有嵌套的Observable),我不想要flatMapWithConcurrency(因為它有利於舊的Observables,而不是最新的Observables),所以我想要的是flatMapLatestTwo或者某個版本的flatMapLatest,您可以在其中指定並發嵌套Observable的最大數量,例如flatMapLatest(2, selectorFn)

這是我想要的輸出( _X表示嵌套的Observable XeX表示其第X個onNext事件):

_0e0
_0e1
 _1e0
_0e2
 _1e1
  _2e0
 _1e2
  _2e1
   _3e0
  _2e2
   _3e1
    _4e0
   _3e2
    _4e1
   _3e3
    _4e2
    _4e3

這就是flatMapLatest產生的:

_0e0
_0e1
 _1e0
 _1e1
  _2e0
  _2e1
   _3e0
   _3e1
    _4e0
    _4e1
    _4e2
    _4e3

我更喜歡使用現有運營商而不是實現這種低級別的解決方案。

這看起來很幼稚。 我正在尋找改進方法,但這里是:

Rx.Observable.prototype.flatMapLatestN = function (count, transform) {

  let queue = [];

  return this.flatMap(x => {
    return Rx.Observable.create(observer => {

      let disposable;

      if (queue.length < count) {
        disposable = transform(x).subscribe(observer);
        queue.push(observer);
      }
      else {
        let earliestObserver = queue[0];
        if (earliestObserver) {
          earliestObserver.onCompleted();
        }

        disposable = transform(x).subscribe(observer);
        queue.push(observer);
      }

      return () => {
        disposable.dispose();
        let i = queue.indexOf(observer);
        queue.splice(i, 1);
      };
    });
  });
};

測試:

function space(n) {
  return Array(n+1).join(' ');
}

Rx.Observable
  .interval(1000)
  .take(6)
  .flatMapLatestN(2, (x) => {
    return Rx.Observable
      .interval(300)
      .take(10)
      .map(n => `${space(x*4)}${x}-${n}`);
  })
  .subscribe(console.log.bind(console));

它將輸出:

0-1
0-2
0-3
    1-0
0-4
    1-1
0-5
    1-2
    1-3
        2-0
    1-4
        2-1
    1-5
        2-2
        2-3
            3-0
        2-4
            3-1
        2-5
            3-2
            3-3
                4-0
            3-4
                4-1
            3-5
                4-2
                4-3
                    5-0
                4-4
                    5-1
                4-5
                    5-2
                4-6
                    5-3
                4-7
                    5-4
                4-8
                    5-5
                4-9
                    5-6
                    5-7
                    5-8
                    5-9

這是一個使用內置運算符的解決方案。 首先,我們將Observable分割為N個可觀察量,其中每個可觀察量在序列中具有相應的第N個最新項目。 然后我們flatMapLatest每一個並合並它們。

Rx.Observable.prototype.flatMapLatestN = function(N, selector, thisArg) {
    var self = this;
    return Rx.Observable.merge(Rx.Observable.range(0, N).flatMap(function(n) {
        return self.filter(function(x, i) {
            return i % N === n;
        }).flatMapLatest(selector, thisArg);
    }));
}

或者在ES2015中:

Rx.Observable.prototype.flatMapLatestN = function(N, selector, thisArg) {
    const {merge, range} = Rx.Observable;
    return merge(
        range(0, N)
            .flatMap(n => 
                this.filter((x, i) => i % N === n).flatMapLatest(selector, thisArg))
    );
}

使用與戴偉相同的測試:

輸出N=1 (與flatMapLatest相同):

0-0
0-1
0-2
    1-0
    1-1
    1-2
        2-0
        2-1
        2-2
            3-0
            3-1
            3-2
                4-0
                4-1
                4-2
                    5-0
                    5-1
                    5-2
                    5-3
                    5-4
                    5-5
                    5-6
                    5-7
                    5-8
                    5-9

N=2輸出:

0-0
0-1
0-2
0-3
    1-0
0-4
    1-1
0-5
    1-2
    1-3
        2-0
    1-4
        2-1
    1-5
        2-2
        2-3
            3-0
        2-4
            3-1
        2-5
            3-2
            3-3
                4-0
            3-4
                4-1
            3-5
                4-2
                4-3
                    5-0
                4-4
                    5-1
                4-5
                    5-2
                4-6
                    5-3
                4-7
                    5-4
                4-8
                    5-5
                4-9
                    5-6
                    5-7
                    5-8
                    5-9

N=3輸出:

0-0
0-1
0-2
0-3
    1-0
0-4
    1-1
0-5
    1-2
0-6
    1-3
        2-0
0-7
    1-4
        2-1
0-8
    1-5
        2-2
    1-6
        2-3
            3-0
    1-7
        2-4
            3-1
    1-8
        2-5
            3-2
        2-6
            3-3
                4-0
        2-7
            3-4
                4-1
        2-8
            3-5
                4-2
            3-6
                4-3
                    5-0
            3-7
                4-4
                    5-1
            3-8
                4-5
                    5-2
            3-9
                4-6
                    5-3
                4-7
                    5-4
                4-8
                    5-5
                4-9
                    5-6
                    5-7
                    5-8
                    5-9

我的答案是在C#中。 抱歉。

你沒有說明你的觀察結果是熱還是冷。 可能是你的奇怪數字來自這樣一個事實:你的窗口對你的'內部'觀察者進行了新的訂閱,因為它從窗口的第一個被推到了第二個。 我的第一次嘗試做了同樣的事:

var q = Observable.Interval(TimeSpan.FromSeconds(1))
        .Select(i => Observable.Interval(TimeSpan.FromMilliseconds(100))
        .Select(x => $"_{i}e{x}"));

w = q.Zip(q.Skip(1), (prev, curr)=> prev.Merge(curr)).Switch(); 

我認為你很難做任何事情來避免這種情況,除非你創建一個運營商,因為有一個狀態參與管理這個問題。 (顯然有人會在這里證明我的錯!)

這是我的操作員方法,它也恰好支持您要求的參數化。

public static class Ex
{
    public static IObservable<T> SelectManyLatest<T>(this IObservable<IObservable<T>> source, int latest)
    {
        return Observable.Create<T>(o => 
        {
            var d = new Queue<IDisposable>();

            source.Subscribe(os => 
            {
                if(d.Count == latest)
                    d.Dequeue().Dispose();

                d.Enqueue(os.Subscribe(o.OnNext, o.OnError, () => {}));

            }, o.OnError, o.OnCompleted);

            return Disposable.Create(()=>new CompositeDisposable(d).Dispose());
        });     
    }
}

再次,抱歉C#

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM