RxJS 中的 map 与 switchMap

bpo*_*iss 13 rxjs angular

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

Kri*_*han 17

两个运营商是不同的。

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

例如:

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

map:为每个值添加投影。

例如:

//add 10 to each value
const example = source.pipe(map(val => val + 10));
Run Code Online (Sandbox Code Playgroud)


Viv*_*mar 14

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

\n

地图流程图

\n

Jsfiddle 示例 -

\n
var observable = Rx.Observable.interval(1000);\nvar observer = {\n    next: function(value) {\n    console.log(value);\n  }\n};\n\nobservable.map(function(value) {\n    return value*10; \n}).subscribe(observer);\n\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

在此输入图像描述

\n

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

\n

前三个输出值(10、10、10)看起来非常简单。只需根据运算符逻辑将它们分别乘以 1 x 10 = 10 即可。根据前三个值,我们可以说对于每个 OO 值,IO 都会发出其所有值。

\n

这个假设对于第一个输出值 30\xe2\x80\xa6 和第二个输出值 30\xe2\x80\xa6 似乎成立

\n

但\xe2\x80\x99t 它应该发出最终值 30 吗?

\n

这就是 switchMap 逻辑发挥作用的地方。每次 OO 发出一个值时,IO 都会发出其所有值,除非 OO 在 IO 发出其所有值之前发出新值。当 OO 发出值 5 时,我们可以看到这一点,并且我们的最后一个值 30 似乎是 \xe2\x80\x9ccanceled\xe2\x80\x9d。

\n
\n

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

\n
\n

Jsfiddle 示例-

\n
var button = document.querySelector(\'button\');\n\nvar obs1 = Rx.Observable.fromEvent(button, \'click\');\nvar obs2 = Rx.Observable.interval(1000);\n\nobs1.switchMap(\n    event => {\n    return obs2\n  }\n).subscribe(\n (value) => console.log(value)\n);\n\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

最佳用例是当我们想要根据从外部可观察到的数据进行 API 调用时。

\n

阅读更多 -

\n

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

\n


mbo*_*jko 6

是否在某些情况下它根本没有区别?

不,它们是两种完全不同的野兽。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);
Run Code Online (Sandbox Code Playgroud)

还有其他性质类似于switchMap: mergeMap(AKA flatMap), exhaustMap, 的运算符concatMap(有些情况下,所有这些或多或少是相同的),但不是map


Gk *_*mon 6

我总是喜欢视觉解释,而不是文字解释。

地图-

在此处输入图片说明

切换图-

在此处输入图片说明

  • 尝试使用有意义的术语,而不是 A、B、1、2、3、10 等,否则很难说出它们应该是什么 (14认同)
  • 完全困惑 (3认同)
  • 实际上让我们假设它们是来自源的事件或数据。当然,在空闲时间我会尝试以深刻的理解来更新一个好的形象。 (2认同)
  • 经过几个小时的研究,我想“好吧,我想我明白了”,直到我看到这个答案。现在又完全糊涂了 (2认同)

Hun*_*NM2 6

查看2个函数的定义:

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

switchmap<inputType, Observable<outputType>>( asyncFunction: (input: inputType) =>  Observable<outputType> )
Run Code Online (Sandbox Code Playgroud)

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

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

如果在任务 1 完成时发出 observable1_event2。Task1 的所有输出将正常显示,然后任务2 的输出将显示。

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