web-dev-qa-db-fra.com

Angular L'opérateur 6 tuyaux RxJs pour chaîner 3 observables dépendantes

J'ai 3 ressources API restantes dépendantes (disons observables) comme ceci:

1st observable produit un élément en tant que tableau d'utilisateurs, comme ceci:

getUsers(): Observable<User[]>
    [
      {
        "id": 1,
        "name": "Peter",
        "surname": "Smith"
      },
      {
        "id": 2,
        "name": "John",
        "surname": "Wayne"
      },
      ...
    ]

2nd observable peut être utilisé pour récupérer les adresses attribuées à l'utilisateur. Le paramètre d'entrée est donc ID utilisateur et renvoie un élément sous forme de tableau d'adresses:

getUserAddresses(user_id: string): Observable<Address[]>
    [
      {
        "id": 1,
        "city": "London",
        "street": "Wicombe 34"
      },
      {
        "id": 2,
        "city": "Paris",
        "street": "La fever 20"
      },
      ...
    ]

La 3ème observable peut être utilisée pour récupérer les sociétés assignées à l'utilisateur. Le paramètre d'entrée est donc ID utilisateur et renvoie un élément sous forme de tableau de sociétés:

getUserCompanies(user_id: string): Observable<Company[]>
    [
      {
        "id": 1,
        "name": "Fintch CO",
        "state": "France"
      },
      {
        "id": 2,
        "name": "C&C inc.",
        "state": "USA"
      },
      ...
    ]

Je souhaite chaîner ces 3 observables en un seul qui produira à nouveau le résultat sous la forme d'un élément, qui contiendra un tableau d'utilisateurs avec leurs tableaux d'adresses supplémentaires et leur tableau de sociétés, comme suit:

    [
      {
        "id": 1,
        "name": "Peter",
        "surname": "Smith",
        "addreesses": 
               [
                 {
                   "id": "1",
                   "city": "London",
                   "street": "Wicombe 34"
                 },
                 {
                   "id": "2",
                   "city": "",
                   "street": "La fever 20"
                 }
               ],
        "companies": 
               [
                 {
                   "id": "1",
                   "name": "Fintch CO",
                   "state": "France"
                 },
                 {
                   "id": "2",
                   "name": "C&C inc.",
                   "state": "USA"
                 }
               ]
        }
      },
      {
        "id": 2,
        "name": "John",
        "surname": "Wayne",
        "addresses": [...],
        "companies": [...],
      },
      ...
    ]

À quoi devrait ressembler le composite opérateurs pour atteindre cet objectif dans Angular 6 avec RxJs 6? Merci beaucoup pour vos conseils.

11
Peter

Quelque chose comme ça pourrait marcher

getUsers()
.pipe(
  switchMap(users => from(users)),
  mergeMap(user => forkJoin(getAddresses(user.id), getCompanies(user.id))
                   .pipe(map(data => ({user, addresses: data[0], companies: data[1] })))
  tap(data => data.user.addresses = data.addresses),
  tap(data => data.user.addresses = data.companies),
  map(data => data.user),
  toArray()
  )
)

Appliquée à un cas d'utilisation différent, une chaîne similaire est expliquée plus en détail ici .

11
Picci

Pour chaîner des observables, vous pouvez utiliser la fonction flatMap. Cette fonction ressemble alors aux promesses, ce qui signifie que la fonction n’est exécutée que lorsque l’observable est résolu en une valeur.

Il existe également une fonction observable appelée forkJoin qui vous permet d’attendre que plusieurs requêtes asynchrones soient résolues à une valeur.

Exemple:

getUsers().flatMap((users) => {
    // the users variable is the list of users
    var multipleObservables = [];
    users.forEach((u) => {
      multipleObservables.Push(
         getUserAddresses(u.id).map((usersAddresses) => {
            u.addresses = usersAddresses;
            return u;
         });
      );
    });
    return forkJoin(multipleObservables);
}).flatMap((usersWithAddresses) => {
    // the usersWithAddresses variable is an array of users which also have their addresses
    var multipleObservables = [];
    usersWithAddresses.forEach((u) => {
       multipleObservables.Push(
          getUserCompanies(u.id).map((usersCompanies) => {
             u.companies = usersCompanies;
             return u;
          });
       );
    });
    return forkJoin(multipleObservables);
});

Vous pouvez écrire quelque chose comme ceci pour chaîner votre requête et développer vos objets utilisateur.

3
brad mcallister

Voici les opérateurs pour la combinaison, ceux-ci émettent le résultat dans un tableau ( reference ):

Je suggérerais de leur donner à tous une lecture pour déterminer ce que vous préférez et trouver le meilleur pour votre scénario.

J'espère que cela t'aides!

0
Jmsdb