【问题标题】:map vs switchMap in RxJSRxJS 中的 map 与 switchMap
【发布时间】:2019-09-12 09:24:59
【问题描述】:

我阅读了switchMapmap 的文档,但我仍然不完全理解它们的区别。在某些情况下它根本没有影响吗?

【问题讨论】:

标签: angular rxjs


【解决方案1】:

两个运算符不同。

switchMap:将值映射到 observable。取消之前的内部 observable。

Eg:

fromEvent(document, 'click')
  .pipe(
    // restart counter on every click
    // First click: 0, 1, 2...
    // Second click: cancels the previous interval and starts new one. 0, 1, 2...
    switchMap(() => interval(1000))
  )
  .subscribe(console.log);

ma​​p:为每个值添加投影。

Eg:

//add 10 to each value
const example = source.pipe(map(val => val + 10));

【讨论】:

    【解决方案2】:

    比起文字解释,我更喜欢视觉解释。

    Map -

    switchmap -

    【讨论】:

      【解决方案3】:

      在某些情况下它根本没有影响吗?

      没有。他们是两种完全不同的野兽。 switchMap 应该返回一个 observable,map 可以返回任何东西。他们的应用是不同的。它通常是这样的:

      someStream$.pipe(
          switchMap(args => makeApiCall(args)), // must return a stream
          map(response => process(response)) // returns a value of any shape, usually an object or a primitive
      ).subscribe(doSomethingWithResults);
      

      还有其他与switchMap本质上相似的运算符:mergeMap(AKA flatMap)、exhaustMapconcatMap(在某些情况下,所有这些都或多或少是相同的东西),但不是map

      【讨论】:

        【解决方案4】:

        Map - 它的作用类似于数组中的映射。 map 接收从 Observable 发出的每个值,对其执行操作。

        Jsfiddle example -

        var observable = Rx.Observable.interval(1000);
        var observer = {
            next: function(value) {
            console.log(value);
          }
        };
        
        observable.map(function(value) {
            return value*10; 
        }).subscribe(observer);
        
        

        SwitchMap - switchMap 将订阅外部 Observable 内的所有内部 Observable,但不会合并内部 Observable。而是切换到最新的 Observable 并将其传递给链。

        假设顶部的每条橙色垂直线代表 1 秒。这意味着外部 Observable (OO) 在 1、4 和 5.5 秒发出值,而内部 Observable (IO) 在 3 秒内每秒发出值,从订阅后立即开始(时间为零)。

        前三个输出值(10、10、10)看起来很简单。只需根据运算符逻辑为它们中的每一个乘以 1 x 10 = 10。基于这前三个值,我们可以说对于每个 OO 值,IO 都会发出它的所有值。

        这个假设似乎适用于第一个输出值 30……和第二个输出值 30……

        但它不应该发出 30 的最终值吗?

        这就是 switchMap 逻辑的用武之地。每次 OO 发出一个值时,IO 都会发出它的所有值,除非 OO 在 IO 完成发出它的所有值之前发出一个新值。当 OO 发出一个值 5 并且我们的最后一个值 30 似乎被“取消”时,我们可以看到这一点。

        将每个源值投影到一个 Observable 中,该 Observable 合并到输出 Observable 中,仅从最近投影的 Observable 发出值。

        Jsfiddle example-

        var button = document.querySelector('button');
        
        var obs1 = Rx.Observable.fromEvent(button, 'click');
        var obs2 = Rx.Observable.interval(1000);
        
        obs1.switchMap(
            event => {
            return obs2
          }
        ).subscribe(
         (value) => console.log(value)
        );
        
        

        在上面的例子中,无论我点击多少次按钮,我总是会得到从 0 开始的值,因为switchMap 切换到最新的 observable。

        最好的用例是我们想要根据从外部 observable 接收到的数据进行 API 调用。

        阅读更多 -

        https://zach-gollwitzer.medium.com/how-to-read-an-rxjs-marble-diagram-f6e8dfa29781 https://dev.to/bhagatparwinder/map-vs-mergemap-vs-switchmap-5gee https://blogs.msmvps.com/deborahk/higher-order-observable/

        【讨论】:

          【解决方案5】:

          查看 2 个函数的定义:

          map<inputType, outputType>(syncFunction: (input: inputType) => outputType )
          
          switchmap<inputType, Observable<outputType>>( asyncFunction: (input: inputType) =>  Observable<outputType> )
          

          map = 一个异步函数调用一个同步函数(asyncTask => syncTask)

          switchMap = 一个异步函数顺序调用一个异步函数(asyncTask => asyncTask )

          switchMap 示例:

            observable1 calls observable2 means:
                  observable1_event1 => new observable2 asynchronous => Task1
                  observable1_event2 => new observable2 asynchronous => Task2
                  observable1_event3 ...
          

          如果在 task1 未完成时发出 observable1_event2,则 task1 的 Observable2 将通过调用 unsubscribe() 被拒绝。这意味着Task1之后将不再显示输出。

          如果在 task1 完成时发出 observable1_event2。 Task1 的所有输出将正常显示,然后 task2 的输出将显示。

          注意:每个新的 observable2 都可以触发很多事件(observable2_event1、observable2_event2、...)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-12-14
            • 2019-10-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多