Quelqu'un, veuillez expliquer la différence entre SwitchMap et FlatMap en termes de Javascript (en perspective angulaire, rxjs 5)
D'après ce que je comprends.
SwitchMap n'émet que la dernière valeur observable et annule la précédente observable.
faltMap collecte toutes les observations individuelles et renvoie toutes les observations dans un seul tableau sans se soucier de l'ordre des observations. fonctionne de manière asynchrone.
concatMap conserve l'ordre et émet toutes les valeurs observables, fonctionne de manière synchrone
est-ce correct?
comment mergeMap fonctionne-t-il différemment des précédents?
quelqu'un, s'il vous plaît expliquer avec un exemple.
@ZahiC, réponse intéressante - J'aime l'utilisation de la composition fonctionnelle dans l'exemple de code. Si vous me le permettez, j'aimerais l'emprunter pour illustrer quelques points supplémentaires à l'aide d'observables chronométrés.
Ces opérateurs sont tous opérateurs de transformation comme map()
, la caractéristique commune est qu'ils ont une observable outer et inner. La principale différence est la manière dont l'observable extérieur contrôle l'observable intérieur.
Pour les contraster, mon exemple de code les exécute par paires et affiche les valeurs sous la forme [outerValue,innerValue]
. J'ai ajouté des intervalles au test et modifié le délai interne afin qu'il y ait un chevauchement temporel (la formule utilisée est delay((5-x)*200)
).
Ces deux sorties toutes les valeurs, la différence est le ordre.
mergeMap - Commande par observable interne
[0,0], [1,0], [0,1], [2,0], [1,1], [3,0], [2,1], [4,0], [3 , 1], [4,1]concatMap - Commande par observable externe
[0,0], [0,1], [1,0], [1,1], [2,0], [2,1], [3,0], [3,1], [4 , 0], [4,1]
À partir de la sortie, l’émission externe mergeMap peut être retardée dans la séquence, mais concatMap suit une séquence d’émission externe stricte .
Ces deux étranglement la sortie.
switchMap - Accélération par dernier
[3,0], [4,0], [4,1]exhaustMap - Accélérateur par premier
[0,0], [0,1], [4,0], [4,1]
De la sortie, switchMap limite les émissions émises par incomplète interne, mais exhaustMap après émet jusqu'à la fin des précédentes.
J'ai ajouté cela parce que switchmap est souvent utilisé dans les réponses SO dans lesquelles il fallait vraiment utiliser mergeMap.
mergeMap - Commande par observable interne
[0,0], [1,0], [0,1], [2,0], [1,1], [3,0], [2,1], [4,0], [3 , 1], [4,1]switchMap - Accélération par dernier
[3,0], [4,0], [4,1]
Le résultat principal est que la sortie switchMap est imprévisible en fonction du minutage de l'observable interne. Par exemple, si l'intérieur est 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>
En prenant ceci d'un réponse précédente :
Voici un exemple du comportement de chacun des opérateurs lorsque la source est un élément immédiat (0,1,2,3,4) et que la fonction de carte crée un observable qui retarde chaque élément de 500 ms:
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;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.8/Rx.js"></script>
<div class='examples'>
<div onClick='mm()'>mergeMap </div>
<div onClick='fm()'>flatMap</div>
<div onClick='cm()'>concatMap</div>
<div onClick='sm()'>switchMap</div>
<div onClick='em()'>exhaustMap</div>
</div>
Au début, c'est un peu long à saisir, du moins pour moi.
Quoi qu'il en soit, considérez ceci:
flatMap
IS UN AUTRE NOM DE mergeMap
- La méthode mergeMap
accepte un paramètre facultatif concurrency
, qui définit le nombre d'observables pouvant être abonnés simultanément.
concatMap
est égal à mergeMap
avec la simultanéité définie sur 1
avec mergeMap
vous ne perdez aucun événement émis par les observables que vous fusionnez comme vous l'avez suggéré dans votre réponse
switchMap
fonctionne comme vous l'avez décrit (voir cet article de Nice pour plus de détails https://blog.angular-university.io/rxjs-switchmap-operator/ )