用C#术语理解RxJS的Flatmap,FlatmapLatest

Nav*_*vap 8 .net javascript c# rxjs

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

我想了解Map,Flatmap,FlatmapLatest关联以及是否有在C#.NET的任何等价物?

Phi*_*Lho 28

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

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

map,flatMap和flatMapLatest的概念并不明显.我自己是RxJS的初学者,所以我希望我做对了......

map获取可观察的项目并将它们(转换它们)映射到其他东西.例如.可能是对数字的算术运算,将基元转换为对象或从对象中移除键等.

flatMap有几个变体,但基本上它需要一个函数从源可观察的每个项返回一个observable.这产生了一个流流(其中stream = observable = items of items),因此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
Run Code Online (Sandbox Code Playgroud)

flatMapLatest是一个flatMap,其中只发出当前observable的项.如果出现新的observable,则忽略前一个的值.

--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
Run Code Online (Sandbox Code Playgroud)

[编辑]我做了一些代码来更好地理解概念...显示flatMapLatest并不明显......我看到它用于Ajax请求:如果发出一个新的,不需要考虑前一个(s ).

演示:点击任何按钮即可显示原始事件.

  • 单击第一个按钮以查看丰富的事件(使用地图).
  • 单击第二个按钮以1秒为间隔触发5个事件序列(flatMap).如果在序列结束前再次单击,则会看到来自正在运行的observable的交错结果.
  • 第三个按钮的行为类似,但使用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) });
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)