我主要是C#开发人员,在JavaScript中拓展了我的视野,最近偶然发现了一个名为RxJS的库。

我想了解MapFlatmapFlatmapLatest的关系,在C#.Net中是否有任何等效项?

最佳答案

RxJS是Reactive Extensions系列的一部分,该系列以多种语言实现,包括C#(自然,因为Rx现在是Microsoft项目)。

所以,是的,C#中有等效项... :-)

map,flatMap和flatMapLatest的概念并不明显。我本人是RxJS的初学者,所以我希望我做对了...
map接受可观察项,并将其映射(转换)成其他形式。例如。可能是对数字的算术运算,将原语转换为对象或从对象中删除键等。
flatMap有几个变体,但是基本上它需要一个函数,从源可观察项的每个项返回一个可观察项。这样就形成了一个流流(其中stream = observable =项目序列),因此flatMap将其扁平化为单个流/observable,其中所有项目都按顺序排列。
嗯,令人困惑的解释,我担心...让我们用Ascii弹珠来解释。

--A------------------- // First stream
--a1----a2----a3------ // flatMap's function result
-----B---------------- // Second stream
-----b1----b2----b3--- // flatMap's function result
--a1-b1-a2-b2-a3-b3--- // flatMap
flatMapLatest是一个flatMap,其中仅发射当前可观察的项。如果出现新的可观察值,则将忽略前一个的值。
--A------------------- // First stream
--a1----a2----a3------ // flatMapLatest's function result
-----B---------------- // Second stream
-----b1----b2----b3--- // flatMapLatest's function result
--a1-b1----b2----b3--- // flatMapLatest

[编辑]我编写了一些代码以更好地理解这些概念...
显示flatMapLatest并不明显...
我看到它用于Ajax请求:如果发出了新请求,则无需考虑以前的请求。

演示:单击任意按钮将显示原始事件。
  • 单击第一个按钮以查看丰富事件(带有 map )。
  • 单击第二个按钮以1 s的间隔触发一次5个事件的序列(flatMap)。如果在序列结束之前再次单击,则会看到正在运行的观测值的交错结果。
  • 第三个按钮的行为类似,但是使用flatMapLatest时,新单击将删除上一个序列的结果。


  • // Generic code to display results
    
    var results = document.getElementById('results');
    function showHTML(html)
    {
      results.insertAdjacentHTML('beforeend', html);
    }
    function show(text, obj)
    {
      showHTML("<p>" + text + (obj !== undefined ? ': ' + JSON.stringify(obj) : '') + "<p>");
    }
    function showObject(obj)
    {
      show("<p>" + JSON.stringify(obj) + "<p>");
    }
    
    // The real code
    
    var button1 = document.querySelector('#button1');
    var button2 = document.querySelector('#button2');
    var button3 = document.querySelector('#button3');
    var buttonClickStream1 = Rx.Observable.fromEvent(button1, 'click');
    var buttonClickStream2 = Rx.Observable.fromEvent(button2, 'click');
    var buttonClickStream3 = Rx.Observable.fromEvent(button3, 'click');
    
    // Raw
    Rx.Observable.merge(buttonClickStream1, buttonClickStream2, buttonClickStream3)
      .subscribe(
        function(v) { show("Value", v); },
        function(e) { show("Error", e); },
        function() { show("Done"); }
      );
    
    // Map
    buttonClickStream1
      .map(function (e, i)
      {
        e.id = i; // Add id
        e.t = new Date(); // Add timestamp
        return e;
      })
      .subscribe(function(v) { show("Button 1", v) }); // Simplify: no errors, no completion
    
    // FlatMap
    buttonClickStream2
      // Returns several values
      .flatMap(function (e, i)
      {
        return Rx.Observable
          .interval(1000).take(5)
          .flatMap(function (x, j) { return Rx.Observable.of(i + ' ' + j) });
      })
      .subscribe(function(v) { show("Button 2", v) });
    
    // FlatMapLatest
    buttonClickStream3
      // Returns several values but keep only the last one
      .flatMapLatest(function (e, i)
      {
        return Rx.Observable
          .interval(1000).take(5)
          .flatMap(function (x, j) { return Rx.Observable.of(i + ' ' + j) });
      })
      .subscribe(function(v) { show("Button 3", v) });
    <button type="button" id="button1">Test map</button>
    <button type="button" id="button2">Test flatMap</button>
    <button type="button" id="button3">Test flatMapLatest</button>
    <div id="results"></div>
    
    <script src="http://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.6/rx.lite.js"></script>

    09-26 16:57