@ZahiC, réponse cool - j'aime l'utilisation de la composition fonctionnelle dans l'exemple de code. Si je peux me permettre, j'aimerais l'emprunter pour illustrer quelques points supplémentaires en utilisant des observables temporisés.
Extérieur, intérieur et contrôle
Ces opérateurs sont tous opérateurs de transformation comme map()
La caractéristique commune est qu'ils ont une extérieur y intérieur observable. La principale différence est la façon dont l'observable externe contrôles l'observable interne.
Pour les contraster, mon exemple de code les exécute par paires, en produisant des valeurs sous la forme de [outerValue,innerValue]
. J'ai ajouté des intervalles au test, et modifié le délai interne de manière à ce qu'il y ait un certain chevauchement dans le temps (la formule utilisée est la suivante delay((5-x)*200)
).
mergeMap vs concatMap
Ceux-ci produisent tous deux toutes les valeurs la différence est que commander .
mergeMap - Ordre par observable interne
[0,0],[1,0],[0,1],[2,0],[1,1],[3,0],[2,1],[4,0],[3,1],[4,1]
concatMap - Ordre par observable externe
[0,0],[0,1],[1,0],[1,1],[2,0],[2,1],[3,0],[3,1],[4,0],[4,1]
D'après le résultat, l'émission extérieure de mergeMap peut être retardée dans la séquence, mais concatMap suit une séquence d'émission extérieure stricte.
switchMap vs exhaustMap
Ces deux papillon des gaz la sortie.
switchMap - L'accélérateur en dernier lieu
[3,0],[4,0],[4,1]
exhaustMap - L'accélérateur en premier
[0,0],[0,1],[4,0],[4,1]
A partir de la sortie, switchMap étrangle tout incomplet l'intérieur émet, mais les gaz d'échappement étranglent suivant émet jusqu'à ce que les précédentes soient terminées.
mergeMap vs switchMap
Je l'ai ajouté parce que switchmap est souvent utilisé dans les réponses de l'OS alors qu'il faudrait plutôt utiliser mergeMap.
mergeMap - Ordre par observable interne
[0,0],[1,0],[0,1],[2,0],[1,1],[3,0],[2,1],[4,0],[3,1],[4,1]
switchMap - L'accélérateur en dernier lieu
[3,0],[4,0],[4,1]
La principale leçon à retenir est que la sortie de switchMap est imprévisible en fonction du moment de l'observable interne, par exemple si l'observable interne est une http get les résultats peuvent dépendre de la vitesse de connexion.
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>