Problème de compréhension de la sortie observable RXJS
Je suis assez nouveau dans rxjs et j'essaie d'apprendre.
Je lisais cet article moyen et j'essayais de comprendre cette sortie RXJS:
import {Observable} from 'rxjs-es';
let output = Observable.interval(500)
.map(i => [1,2,3,4,5,6][i]);
let result = output.map(num1 => num1)
.filter(num1 => num1 > 4)
.reduce((num1, num2) => num1 + num2);
result.subscribe(number => console.log(number));
Sortie: 27
Je ne comprends pas comment la sortie s'est avérée être 27 et comment cette réduction fonctionne (et quels sont ces deux arguments pour le réducteur).
Quelqu'un peut-il m'éclairer sur ce qui se passe? (J'ai essayé de l'exécuter sur codesandbox mais cela génère une erreur lorsque j'exécute ce code)
Réponses
Compréhension Filteret Reduceopérateurs
Comme d'autres l'ont mentionné dans les commentaires, l'article auquel vous faites référence utilise une ancienne version de rxjs qui a une syntaxe différente. Pour cet exemple, j'utiliserai la nouvelle syntaxe qui a commencé dans la version 6.
Dans rxjs, il existe différents opérateurs disponibles pour transformer les valeurs émises via un flux. En règle générale, ceux-ci sont importés comme:
import { filter, reduce } from 'rxjs';
Il existe également de nombreuses fonctions de générateur disponibles pour créer un flux de valeurs. intervalest l'une de ces fonctions qui va créer un flux qui émet des entiers séquentiels toutes les nmillisecondes. Importé comme:
import { interval } from 'rxjs/operators';
Créons un flux simple:
number$ = interval(1000); // emit number every 1 second
// output: 0, 1, 2, 3, 4, 5...
Nous pouvons appliquer des opérateurs à ce flux pour transformer les émissions:
L'utilisation de filterest assez simple. Il émet simplement des valeurs qui passent le test de vérité donné (exactement comme la Array.filter()méthode).
numbersLessThan4$ = numbers$.pipe(
filter(number => number < 4)
);
// output: 0, 1, 2, 3
L' reduceopérateur est un peu plus complexe et se comporte comme la Array.reduce()méthode. Une fonction est appliquée à chaque valeur émise et est capable de stocker une valeur qui peut être référencée lors de l'évaluation de l'émission suivante.
reduceprend deux paramètres. La première est une fonction qui reçoit l'émission actuelle ( cur) et le résultat cumulé précédent ( acc) et renvoie une nouvelle valeur accumulée. La seconde est une valeur initiale pour acc.
exemple:
sumOfNumbers$ = numbers$.pipe(
reduce((acc, cur) => acc + cur, 0)
);
Alors, regardons ce que reducefait quand numbers$émet les 3 premiers nombres:
- 0
curreçoit la valeur d'émission actuelle0acccommence par la valeur par défaut fournie0- l'expression
acc + curretourne0
- 1
curreçoit la valeur d'émission actuelle1accreçoit la valeur précédemment renvoyée0- l'expression
acc + curretourne1
- 2
curreçoit la valeur d'émission actuelle2accreçoit la valeur précédemment renvoyée1- l'expression
acc + curretourne3
Donc c'est cool. Nous pouvons intégrer beaucoup de logique dans une simple ligne de code. Une chose importante à ce sujet reduceest qu'il n'émettra pas tant que l'observable source n'est pas terminée. Actuellement, numbers$ne se termine jamais ( interval()émet des entiers séquentiels indéfiniment).
Nous pouvons utiliser l' take()opérateur pour compléter le flux après l'émission d'un certain nombre de valeurs.
Exemple:
numbers$ = interval(1000).pipe(take(5)); // completes after 5 emissions
sumOfNumbers$ = numbers$.pipe(
// receives 5 values (0, 1, 2, 3, 4) and performs the logic described above.
reduce((acc, cur) => acc + cur, 0)
);
// output: 10
Plusieurs opérateurs peuvent être utilisés pour transformer les émissions. Fournissez simplement plusieurs dans le pipe():
sumOfNumbersLessThan4$ = numbers$.pipe(
filter(number => number < 4),
reduce((acc, cur) => acc + cur, 0)
);
// output: 6