IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Angular Discussion :

Bonne pratique pour charger les données une seule fois


Sujet :

Angular

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 067
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 2 067
    Par défaut Bonne pratique pour charger les données une seule fois
    Bonjour,

    je voudrais savoir les bonnes pratiques pour charger les données d'un webservice une seule fois, actuellement je fais comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    private companies: Company[];
      getCompanies(): Observable<Company[]> {
        if (!this.companies) {
          this.httpClient.get<Company[]>(`${this.baseUrl}api/Companies/GetShortListCompanies/${this.msalService.getAccount().accountIdentifier}`).pipe(share()).subscribe(r => this.companies = r);
        }
        return of(this.companies);
      }
    est-ce qu'il y a une meilleure façon de faire ?

    Seconde question, c'est une appli que j'ai repris et il y a souvent ce type de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     private companies$: BehaviorSubject<Company[]> = new BehaviorSubject(undefined);
      private isCompaniesRequestOnGoing: boolean;
    getCompanies(): Observable<Company[]> {
        this.companies$.pipe(
          take(1)
        ).subscribe((companies) => {
          if (!this.isCompaniesRequestOnGoing) {
            this.isCompaniesRequestOnGoing = true;
            this.httpClient.get(`${this.baseUrl}api/Companies/GetShortListCompanies/${this.msalService.getAccount().accountIdentifier}`).pipe(
              take(1)
            ).subscribe((companies: Company[]) => {
              console.log(companies);
              this.companies$.next(companies);
            }, error => {
              console.log(error);
            }, () => {
              this.isCompaniesRequestOnGoing = false;
            });
          }
        });
     
        return this.companies$;
      }
    Je n'arrive pas à comprendre à quoi il sert ? pourquoi subscribe sur le behaviorSubject qu'on renvoi ?

  2. #2
    Membre extrêmement actif
    Avatar de dukoid
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2012
    Messages
    2 100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2012
    Messages : 2 100
    Par défaut
    hou la ! le code de la seconde question c'est ..heu comment dire -->
    j'ai l'impression que ce qu'il voulait faire c'est ce que tu veux faire et c'est ta question


    en général, on relance toujours la requête pour obtenir la dernière version au cas ou il aurait été modifié.
    mais s'il n'est pas sensé être modifié il faut le stocker !

  3. #3
    Membre Expert

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 067
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 2 067
    Par défaut
    Comment faire un bon mix des 2, mon premier exemple fonctionne pas avec certains contrôle comme le mat-list ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
      private companies: Company[];
      private companies$: BehaviorSubject<Company[]> = new BehaviorSubject([]);
     
      getCompanies(): Observable<Company[]> {
        if (!this.companies) {
          this.httpClient.get<Company[]>(`${this.baseUrl}api/Companies/GetShortListCompanies/${this.msalService.getAccount().accountIdentifier}`).pipe(share()).subscribe(r => {
            this.companies = r;
            this.companies$.next(r);
          });
        }
        return this.companies$;
      }
    Avec ce code mon contrôle fonctionne, mais je pense il y a moyen de faire mieux, (je peux remplacer companies par un booléen mais c'est pas le noeud du problème)

  4. #4
    Membre extrêmement actif
    Avatar de dukoid
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2012
    Messages
    2 100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2012
    Messages : 2 100
    Par défaut
    un composant Web angular possède des cycles de vie
    on met dans ngOnInit tout l'initialisation
    car ngOnInit () est appelé qu'une seule fois !



    Avec la programmation reactive et dynamique, ce n'est pas de la programmation classique, ici les données ont les récupères X temps après (le temps de la requete) donc faut toujours prendre en compte ça et les observables permettent de bien gérer ces problèmes

    BehaviorSubject car il fournit aux souscripteurs les dernières valeurs récupérés meme si on souscrit plus tard.
    alors qu'un simple subject , attends l'arrivées de futur valeur pour les fournirs aux souscripteurs


    voici une bonne pratique via les observables, c'est aussi simple que ça :

    service singleton: CompaniesService.ts
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    private companiesSubject$: BehaviorSubject<Company[]> = new BehaviorSubject([]);
     
    initializeCompanies() {
        this.getCompaniesApi().subscribe((companies: Company[]) => {
          this.companiesSubject$.next(companies);
        });
    }
     
    getCompaniesApi(): Observable<Company[]> {
      return this.httpClient.get<Company[]>(`${this.baseUrl}api/Companies/GetShortListCompanies/${this.msalService.getAccount().accountIdentifier}`)
    }
     
    getCompaniessubject():   BehaviorSubject<Company[]> {
       return this.companiesSubject$;
    }
    app.component.ts
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    ...
    ...
     
    ngOnInit(): void {      // j'initialise les données dans le composant principal, car il sera demandé dans les composants enfants et ils seront disponible via l'observable
     
       this.companiesService.initializeCompanies();
    }
    partout ou tu as besoin des données, dans un composant ou même dans un autre service :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // dans un composant :
    ...
    subscription: Subscription;
    ...
    ngOnInit(): void {  
    
      this.subscription = this.companiesService.getCompaniessubject().subscribe((companies: Company[]) => {
        console.log(companies);
        ...
        ...
      }
    }
    
    ngOnDestroy(): void {  
       this.subscription.unsubscribe();          // il faut toujours se désinscrire  !!!!!!!!
    }
    disons qu'un composant toto enfant de app.composant (comme l'est toute l'application en général)
    ce composant souscrit à companiesSubject

    app.component lance la requete

    2 cas se présente :
    - le composant toto arrive dans son ngOnInit et la requête n'est pas terminé, pas de problème, la soubscription va rester l'écoute l'arrivée
    - le composant toto arrive dans son ngOnInit et la requête est déjà terminé, pas de problème, la soubscription va envoyer le dernier résultat car c'est un BehaviorSubject

    pour être perfectionniste j'utiliserais plutôt un ReplaySubject qu'un BehaviorSubject

    const mySubject = new ReplaySubject(1); // 1 pour envoyer que le dernier résultat

    ReplaySubject c'est un BehaviorSubject mais pas besoin de l'initialiser avec une valeur, comme le fait dans ton code : private companiesSubject$: BehaviorSubject<Company[]> = new BehaviorSubject([]);
    avec un tableau vide ! c'est inutile d'envoyer un tableau vide ... autant que le sujet attends l'arrivée de la requete



    normalement ceci répondra à ta question (1) et (2)

  5. #5
    Membre Expert

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 067
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 2 067
    Par défaut
    Après je connais bien la prog avec angular j'en fait depuis quelques années mais on perd beaucoup quand on passe d'angularJs à angular2+ (ou vis versa), pour la prog reactive j'essaye de m'y mettre sérieusement justement.

    Si j'appel l'initializeCompanies 2 fois il me fera 2 appel de Webservices? si je vais sur une autre page et je reviens sur celle-ci ?

    Je rentre rarement dans des cas ou un component parent appellera l'initialisation pour ces enfants, j'ai souvent besoin des mêmes infos sur plusieurs page mais pas forcément toute, donc je met pas ça dans l'app component.


    Je viens de reprendre l'app la semaine dernière j'ai déjà refais 90% de l'archi côté serveur, là j'ai essayé de reprendre la plupart des choses faites en angular mais je t'avoue ne pas avoir compris ce qui avait été fait et le but

  6. #6
    Membre extrêmement actif
    Avatar de dukoid
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2012
    Messages
    2 100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2012
    Messages : 2 100
    Par défaut
    service singleton: CompaniesService.ts
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    private companiesSubject$: BehaviorSubject<Company[]> = new BehaviorSubject([]);
    isInitialized = false;
     
    initializeCompanies() {
      if (!this.isInitialized) {
        this.getCompaniesApi().subscribe((companies: Company[]) => {
          this.isInitialized = true;
          this.companiesSubject$.next(companies);
        });
      }
    }
     
    getCompaniesApi(): Observable<Company[]> {
      return this.httpClient.get<Company[]>(`${this.baseUrl}api/Companies/GetShortListCompanies/${this.msalService.getAccount().accountIdentifier}`)
    }
     
    getCompaniessubject():   BehaviorSubject<Company[]> {
       return this.companiesSubject$;
    }

    dans tous les composants qui ont besoin d'accéder à la donnée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    // dans un composant :
    ...
    subscription: Subscription;
    ...
    ngOnInit(): void {  
      this.companiesService.initializeCompanies();
     
      this.subscription = this.companiesService.getCompaniessubject().subscribe((companies: Company[]) => {
        console.log(companies);
        ...
        ...
      }
    }
     
    ngOnDestroy(): void {  
       this.subscription.unsubscribe();          // il faut toujours se désinscrire  !!!!!!!!
    }
    ...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [MySQL-5.7] Bonnes pratiques pour stocker les user/pwd d'accès à la base de données en PHP
    Par berthos dans le forum Administration
    Réponses: 2
    Dernier message: 22/01/2019, 21h07
  2. Réponses: 3
    Dernier message: 18/01/2019, 19h30
  3. Charger les données une seule fois ou dans chaque session.
    Par archer dans le forum Développement Web en Java
    Réponses: 4
    Dernier message: 28/10/2010, 12h18
  4. Réponses: 7
    Dernier message: 23/03/2009, 22h38
  5. Réponses: 4
    Dernier message: 01/10/2008, 08h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo