Problème de compréhension de la sortie observable RXJS

Aug 27 2020

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

1 BizzyBob Aug 27 2020 at 11:26

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
    • cur reçoit la valeur d'émission actuelle 0
    • acc commence par la valeur par défaut fournie 0
    • l'expression acc + curretourne0
  • 1
    • cur reçoit la valeur d'émission actuelle 1
    • acc reçoit la valeur précédemment renvoyée 0
    • l'expression acc + curretourne1
  • 2
    • cur reçoit la valeur d'émission actuelle 2
    • acc reçoit la valeur précédemment renvoyée 1
    • 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