【问题标题】:What does the `map` method mean in RxJS?RxJS 中的 map 方法是什么意思?
【发布时间】:2015-01-23 10:37:32
【问题描述】:

通过阅读本教程http://reactive-extensions.github.io/learnrx/,我正在学习RxJS

我很难理解Observablemap 方法。 Array 版本的map 非常简单明了。我不知道在Observable 的情况下map 到底是什么意思(以及为什么它有一个名为select 的别名?!)。

这是文档告诉我的。可能对大多数初学者没有帮助...

通过合并元素的索引将可观察序列的每个元素投影到新形式中。这是 select 方法的别名。

event 的上下文中,我不理解map。 例如,下面的代码完全符合我的预期。我认为这段代码是:“从#btn的事件流中收听click-event”。

var btnClicks, observable;

btnClicks = Rx.Observable.fromEvent($('#btn'), "click");

observable = btnClicks.subscribe(function(e) {
	console.log(e);
});

但是当它变成这样时会发生什么?

var btn2Clicks, btnClicks, observable;

btnClicks = Rx.Observable.fromEvent($('#btn'), "click");

btn2Clicks = Rx.Observable.fromEvent($('#btn2'), "click");

observable = btnClicks.map(function(e) {
  return btn2Clicks;
}).subscribe(function(e) {
  console.log(e);
});

我的想法是使用map 将点击事件的集合转换为另一个事件集合的集合。 filter 很容易理解,就像filter 的意思一样,只参加我感兴趣的活动,跳过其他活动。但是mapevent 的上下文中呢?如果它意味着像数组版本一样“将一个集合转换为另一个集合”,为什么在点击#btn 时它仍然会触发?

我的意思是我已经将它映射到另一个集合,现在它不再是 #btn 的点击事件的集合,但它是一个新的集合...但是当 #btn 被点击时它仍然会触发对我有感觉。

【问题讨论】:

    标签: javascript rxjs


    【解决方案1】:

    map 对 Observables 的作用与对数组的作用完全相同。您使用map 将项目集合转换为不同项目的集合。如果您将 Observable 视为项目的集合(就像数组也是项目的集合一样),这会有所帮助,至少从观察者的角度来看是这样。

    例如,将您编写的以下 2 个方法用于某些数组:

    function multiplyByTwo(collection) {
        return collection.map(function (value) {
            return value * 2;
        });
    }
    
    function removeZeroes(collection) {
        return collection.filter(function (value) {
            return value !== 0;
        });
    }
    
    var a = [1, 2, 3, 4, 0, 5];
    var b = multiplyByTwo(a); // a new array [2, 4, 6, 8, 0, 10]
    var c = removeZeroes(b); // a new array [2, 4, 6, 8, 10]
    

    您可以将这些相同的函数用于可观察对象:

    var a = Rx.Observable.of(1, 2, 3, 4, 0, 5);
    var b = multiplyByTwo(a); // a new observable [2, 4, 6, 8, 0, 10]
    var c = removeZeroes(b); // a new observable [2, 4, 6, 8, 10]
    

    这是可能的,因为 RxJ 的 observables 实现了数组运算符,如 mapfilter,具有与数组完全相同的语义。如果您知道它们如何用于数组,那么您就会知道它们如何用于可观察对象。

    这个技巧是dual nature of observables and enumerables的结果。

    如果您完成正在查看的交互式教程,它实际上会引导您完成此过程。我相信它会从为数组编写 map 运算符开始,然后在后面的教程中偷偷添加一个 observable 作为源。

    附: 它是select 的别名,因为它的历史:Reactive Extensions 最初是在 .NET 中实现的,后来被移植到其他语言。 Rx.NET 使用与 .NET 的 LINQ 相同的运算符(因为 IObservableIEnumerable 的对偶)。 LINQ 的映射运算符称为Select(它的过滤运算符称为Where)。这些名称来自 LINQ 的起源。构建 LINQ 的目标之一是使使用 C# 编写数据库查询成为可能。因此,他们为许多运算符采用了 SQL 命名约定(LINQ SELECT 直接映射到 SQL SELECT,LINQ WHERE 映射到 SQL WHERE 等)。

    【讨论】:

    • 谢谢!现在我知道为什么有些方法有别名了。但是我还是看不懂event上下文中的map操作。我编辑了问题,希望你能回答我在处理事件时map是什么意思。
    • @Brandon 但是 map 函数什么时候迭代?我的意思是,当你映射到一个数组时,你已经拥有了数组中的所有元素,并且它在每个元素中迭代 log(n) 次。当您在 Observable 上进行 .map 处理时,observable 是否已经接收到所有元素(并且它遍历每个元素)或者函数(在 map 块内)是否在每个元素(事件)到达时对其进行操作?那么对于 Observables,map 是充当迭代器(就像它对普通数组一样)还是 .map 更像是每个事件(元素)通过的装饰器?
    • @BenjaminMcFerren Observables 是基于推送的(在数据可用时将数据push 发送给订阅者(通过map 等任何运营商)。所以,是的,用你的话说,Observable 操作符就像事件装饰器。
    • 对此我不太确定。你能解释一下吗?我们如何将具有 subscribe 方法而不是 map 的 observable 传递给“multiplyByTwo”函数,并期望它会通过该流进行一些操作 O.o
    • 这个答案是为旧版本的 RxJs 编写的,其中 Observable 原型直接包含所有方法。最近的版本只有 subscribe() 和 pipe(),你应该使用 pipe() 来创建你的函数链,比如 map()。所以上面的例子不再适用了。从概念上讲是一样的,但现在 Observable API 与 Array API 有所不同。
    【解决方案2】:

    Rxjs 中的映射用于投影,这意味着您可以将数组转换为全新的数组。为了理解 Map 是如何工作的,我们可以使用普通的 javascript 实现我们自己的 map 函数。

    Array.prototype.map = function(projectionFunction){
      var results=[];
      this.forEach(function(item) {
        results.push(projectionFunction(item));
      });
      return results;
    };
    

    你可以看到我写了一个map函数,它接受一个匿名函数作为参数。这将是您应用投影来转换数组的函数。在 map 函数中,你可以看到迭代数组中的每一项,通过传递每一项来调用项目函数,最后投影函数的结果将推送到结果数组。

    JSON.stringify([1,2,3].map(function(x){return x+1;}))
    

    输出

    [2,3,4]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-16
      • 1970-01-01
      • 1970-01-01
      • 2016-10-17
      • 2013-11-02
      • 2013-03-29
      • 2013-01-30
      相关资源
      最近更新 更多