rxjs中的flatMap,mergeMap,switchMap和concatMap?

时间:2018-04-06 18:02:54

标签: rxjs observable

有人请用Javascript解释SwitchMap和FlatMap之间的区别(角度透视,rxjs 5)

根据我的理解。

SwitchMap 仅发出最新的可观察值并取消之前的可观察值。

faltMap 收集所有单独的observable并返回单个数组中的所有observable,而不关心可观察的顺序。异步工作。

concatMap 保留顺序并发出所有可观察值,同步工作

是吗?

mergeMap 与上面的工作原理有何不同?

有人,请举例说明。

6 个答案:

答案 0 :(得分:11)

previous answer

获取此信息
  • flatMap / mergeMap - 立即为任何源项创建一个Observable,所有以前的Observable都保持活动
  • concatMap - 在创建下一个Observable之前等待上一个Observable完成
  • switchMap - 对于任何源项,完成上一个Observable并立即创建下一个
  • exhaustMap - 上一个Observable未完成时会忽略源项目

下面是一个示例,说明当源是直接项(0,1,2,3,4)时每个运算符的行为,并且map函数创建一个将每个项延迟500ms的Observable:

updateChildren(...)
const { mergeMap, flatMap, concatMap, switchMap, exhaustMap } = Rx.operators;

const example = operator => () =>
  Rx.Observable.from([0,1,2,3,4])
  .pipe(
    operator(x => Rx.Observable.of(x).delay(500))
  )
  .subscribe(console.log, () => {}, () => console.log(`${operator.name} completed`));

const mm = example(mergeMap);
const fm = example(flatMap);
const cm = example(concatMap);    
const sm = example(switchMap);
const em = example(exhaustMap);
.examples > div {
  cursor: pointer;
  background-color: #4CAF50;
  color: white;
  padding: 7px 16px;
  display: inline-block;
}

答案 1 :(得分:5)

@ ZahiC,很酷的回答 - 我喜欢在代码示例中使用功能组合。如果我愿意,可以借用它来说明使用定时观察的几个额外点。

外部,内部和控制

这些运算符都是transformation operators,如map(),常见的功能是它们具有外部内部可观察。关键的区别在于外部可观察的控制内部可观察的方式。

为了对比它们,我的代码示例成对运行它们,以[outerValue,innerValue]形式输出值。我已经在测试中添加了间隔,并改变了内部延迟,以便在时间上有一些重叠(使用的公式是delay((5-x)*200))。

mergeMap vs concatMap

这两个输出所有值,区别在于排序

  

mergeMap - 按内部观察顺序排序   [0,0],[1,0],[0,1],[2,0],[1,1],[3,0],[2,1],[4,0],[3 ,1],[4,1]

     

concatMap - 外部可观察的订单
  [0,0],[0,1],[1,0],[1,1],[2,0],[2,1],[3,0],[3,1],[4 ,0],[4,1]

从输出中,mergeMap外部发射可以在序列中延迟,但concatMap遵循严格的外部发射序列。

switchMap vs exhaustMap

这两个节流输出。

  

switchMap - 最后一次节流   [3,0],[4,0],[4,1]

     

排气地图 - 首先加油   [0,0],[0,1],[4,0],[4,1]

从输出中,switchMap限制任何不完整内部发射,但排除后面的限制,直到先前的完成。

mergeMap与switchMap

我把它扔进去是因为switchmap经常用在SO答案中,其中应该使用mergeMap。

  

mergeMap - 按内部观察顺序排序   [0,0],[1,0],[0,1],[2,0],[1,1],[3,0],[2,1],[4,0],[3 ,1],[4,1]

     

switchMap - 最后一次节流   [3,0],[4,0],[4,1]

主要内容是switchMap输出不可预测,具体取决于内部可观察的时间,例如,如果内部是 http get ,结果可能取决于连接速度。



console.clear()
const { mergeMap, flatMap, concatMap, switchMap, exhaustMap, delay, map, take, toArray } = Rx.operators;

const note = {
  mergeMap:  'Order by inner observable', 
  concatMap: 'Order by outer observable', 
  switchMap: 'Throttle by last', 
  exhaustMap: 'Throttle by first', 
}
const title = (operator) => {
  const opName = operator.name.replace('$1','')
  return `${opName} - ${note[opName]}`
}
const display = (x) => {
  return map(y => `[${x},${y}]`)
}
const inner = (x) => Rx.Observable.timer(0,500)
.pipe(
  delay((5-x)*200),
  display(x),
  take(2)
)

const example = operator => () => {
  Rx.Observable.interval(500).take(5)
  .pipe(
    operator(x => inner(x)),
    toArray(),
    map(vals => vals.join(','))
  )
  .subscribe(x => {
    console.log(title(operator))
    console.log(x)
  });
};

const run = (fn1, fn2) => {
  console.clear()
  fn1()
  fn2()
}
const mmVcm = () => run(example(mergeMap), example(concatMap));
const smVem = () => run(example(switchMap), example(exhaustMap));
const mmVsm = () => run(example(mergeMap), example(switchMap));

.examples > div {
  cursor: pointer;
  background-color: #4CAF50;
  color: white;
  padding: 7px 16px;
  display: inline-block;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.8/Rx.js"></script>

<div class='examples'>
  <div onClick='mmVcm()'>mergeMap vs concatMap </div>
  <div onClick='smVem()'>switchMap vs exhaustMap</div>
  <div onClick='mmVsm()'>mergeMap vs switchMap </div>
</div>
&#13;
&#13;
&#13;

答案 2 :(得分:2)

至少在我看来,这一开始有点长,

无论如何,请考虑一下:

flatMap mergeMap的另一个名称 - mergeMap方法接受一个可选参数concurrency,该参数定义了可以同时订阅的Observable数量

concatMap等于mergeMap且并发设置为1

mergeMap你不会丢失你正在按照你在答案中的建议合并的Observable所发出的任何事件

switchMap按照您的描述工作(有关详细信息,请参阅此文章https://blog.angular-university.io/rxjs-switchmap-operator/

答案 3 :(得分:2)

在下面的大理石图中,以 *映射的源流以 5ms 10ms 20ms 发射>到timer(0, 3),限制为3种排放:

mergeMap vs exhaustMap vs switchMap vs concatMap

在此处使用此大理石图:"mergeMap vs exhaustMap vs switchMap vs concatMap"

已经有了所有这些出色的答案,我想添加一个更直观的解释

希望它对某人有帮助

答案 4 :(得分:2)

这是思考不同类型地图之间差异的另一种方法。这帮助我绕开了头脑。我希望它可以帮助其他人。

请考虑以下来源:

  • 从字母表中产生小写字母的来源:a,b,c和d
  • 4个独立的“单词”来源,每个来源产生3个单词,以字母中的特定字母-a,b,c或d-然后完成

为说明不同类型的地图之间的区别,我们将使用每个不同的地图查看从不同字母到对应于该字母字母的“单词”源的条目。

Map

这与其他地图不同,因为它没有引入其他可观测的来源。它将输入的值转换为另一个值。

因此,通过将输入转换为大写的Map的小写源的输出将是:

Input: a,b,c,d

Output: A, B, C, D

Switch Map

这会将每个输入转换为另一个源,将输出切换为来自该新源(即订阅该新源)。当另一个Alpha输入到达时,“单词”源将发生变化(我们取消订阅先前的“单词”源)。

Input: a,b,c,d

Output: animal, aardvark, bull, baker, beach, cow, dog, day, dinner

Concat Map

类似于switchMap,不同之处在于Concat等到每个源都完成后才继续进入下一个。

Input: a,b,c,d

Output: animal, aardvark, axe, bull, baker, beach, cow, car, cat, dog, day, dinner

Exhaust Map

类似于Concat Map,不同之处在于它将忽略仍在完成最后一个源时输入的所有输入。下面的示例假定Alpha输入“ b”和“ d”都在前一个映射源仍在完成时进入,因此将其忽略。

Input: a,b,c,d

Output: animal, aardvark, axe, cow, car, cat

Merge Map(又称平面地图)

就像concatMap一样,每个源都可以运行完成,但是在其他源仍在运行时可以启动一个新源-因此序列重叠。

Input: a,b,c,d

Output: animal, aardvark, bull, axe, baker, cow, car, beach, dog, day, cat, dinner

答案 5 :(得分:0)

前段时间,我做了一个使用请求的运算符的演示/示例。

https://stackblitz.com/edit/rxjs-map-operators

您可以选择一个间隔或单击以发出外部可观察值。 对于内部可观察对象,您可以选择发出间隔(3个项目)还是发出http请求。

它将在选择内容下方打印结果。