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

  1. #1
    Expert confirmé

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 065
    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 065
    Points : 4 229
    Points
    4 229
    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 expert
    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
    Points : 3 004
    Points
    3 004
    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
    Expert confirmé

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 065
    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 065
    Points : 4 229
    Points
    4 229
    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 expert
    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
    Points : 3 004
    Points
    3 004
    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
    Expert confirmé

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 065
    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 065
    Points : 4 229
    Points
    4 229
    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 expert
    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
    Points : 3 004
    Points
    3 004
    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  !!!!!!!!
    }
    ...

  7. #7
    Expert confirmé

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 065
    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 065
    Points : 4 229
    Points
    4 229
    Par défaut
    J'étais pas loin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
      getCompanies(): Observable<Company[]> {
        if (!this.companiesLoaded) {
          this.httpClient.get<Company[]>(`${this.baseUrl}api/Companies/GetShortListCompanies/${this.msalService.getAccount().accountIdentifier}`).pipe(share()).subscribe(r => {
            this.companiesLoaded = true;
            this.companies$.next(r);
          }, error => {
            console.log(error);
          });
        }
        return this.companies$;
      }
    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
    24
    25
    26
    27
     
     ngOnInit(): void {
        this.formCtrls.companyCtrl.valueChanges.subscribe((value) => {
          if (value && value.length) {
            let company = value[0];
            this.companyName = company.shortName;
            this.clients = this.companyService.getContactsForCompany(company);
          }
        });
     
        this.formCtrls.clientCtrl.valueChanges.subscribe((value) => {
          if (value && value.length) {
            let client = value[0];
            this.clientName = client.name;
          }
        });
     
        this.companies = this.companyService.getCompanies();
     
        this.refDatas = this.refDataService.allRefDatas$;
     
        this.authService.user$.subscribe(u => {
          if (u) {
            this.userId = u.id
          }
        });
      }
    par contre faudrait que je rajoute le ngdestroy pour éviter de bouffer des ressources inutilement 👍
    faudrait peut être que je modifie ce refdata au passage pour rendre privé le behaviour

  8. #8
    Membre éprouvé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Janvier 2019
    Messages
    707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2019
    Messages : 707
    Points : 1 030
    Points
    1 030
    Par défaut
    utilise plutot le ReplaySubject comme indiqué pour être parfait !

  9. #9
    Membre expert
    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
    Points : 3 004
    Points
    3 004
    Par défaut
    j'ai fais une legère modification, est ce que tu vois pourquoi ?

    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
     
      getCompanies(): Observable<Company[]> {
        if (!this.companiesLoaded) {
     
          this.companiesLoaded = true;
          this.httpClient.get<Company[]>(`${this.baseUrl}api/Companies/GetShortListCompanies/${this.msalService.getAccount().accountIdentifier}`).pipe(share()).subscribe(r => {
     
            this.companies$.next(r);
          }, error => {
            this.companiesLoaded = false;
            console.log(error);
          });
        }
        return this.companies$;
      }
    bonne pratique :

    après il y a le niveau expert, en utilisant un interceptor.
    dans ton code tu fais tes requêtes habituelles et c'est l'interceptor via un cache qui va gérer les demandes.

    en effet, l'interceptor va intercepter toutes les requêtes
    ensuite il regarde dans le cache si il a déjà effectué cette requête, si oui il envoi le résultat du cache
    sinon il effectue la requête et met en cache le résultat pour une éventuelle demande ultérieur

    /interceptors/CachingInterceptor.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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    import { Injectable } from '@angular/core';
    import { HttpEvent, HttpRequest, HttpResponse, HttpInterceptor, HttpHandler } from '@angular/common/http';
     
    import { Observable } from 'rxjs/Observable';
    import { startWith, tap } from 'rxjs/operators';
    import 'rxjs/add/observable/of';
     
    import { RequestCache } from './request-cache.service';
     
    @Injectable()
    export class CachingInterceptor implements HttpInterceptor {
      constructor(private cache: RequestCache) {}
     
      intercept(req: HttpRequest<any>, next: HttpHandler) {
        const cachedResponse = this.cache.get(req);
        return cachedResponse ? Observable.of(cachedResponse) : this.sendRequest(req, next, this.cache);
      }
     
      sendRequest(
        req: HttpRequest<any>,
        next: HttpHandler,
        cache: RequestCache): Observable<HttpEvent<any>> {
        return next.handle(req).pipe(
          tap(event => {
            if (event instanceof HttpResponse) {
              cache.put(req, event);
            }
          })
        );
      }
    }
    /services/RequestCache.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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    import { Injectable } from '@angular/core';
    import { HttpRequest, HttpResponse } from '@angular/common/http';
     
    const maxAge = 30000;
    @Injectable()
    export class RequestCache  {
     
      cache = new Map();
     
      get(req: HttpRequest<any>): HttpResponse<any> | undefined {
        const url = req.urlWithParams;
        const cached = this.cache.get(url);
     
        if (!cached) {
          return undefined;
        }
     
        const isExpired = cached.lastRead < (Date.now() - maxAge);
        const expired = isExpired ? 'expired ' : '';
        return cached.response;
      }
     
      put(req: HttpRequest<any>, response: HttpResponse<any>): void {
        const url = req.url;
        const entry = { url, response, lastRead: Date.now() };
        this.cache.set(url, entry);
     
        const expired = Date.now() - maxAge;
        this.cache.forEach(expiredEntry => {
          if (expiredEntry.lastRead < expired) {
            this.cache.delete(expiredEntry.url);
          }
        });
      }
    }
    // le cache est limité à 30 sec, tu peux le modifier ou le supprimer si tu ne veut pas de limite de temps ! (dans ce cas, faire modif dans le code)


    app.module.ts
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
    import { RequestCache } from './request-cache.service';
    import { CachingInterceptor } from './caching-interceptor.service';
     
    // ...
     
    providers: [
        RequestCache,
        { provide: HTTP_INTERCEPTORS, useClass: CachingInterceptor, multi: true }
      ],
     
    // ...

    et à l'utilisation, pas besoin d'observable ... tu fais juste ta requête et c'est l'interceptor qui gère l'envoi des données :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     this.httpClient.get<Company[]>(`${this.baseUrl}api/Companies/GetShortListCompanies/${this.msalService.getAccount().accountIdentifier}`)

  10. #10
    Expert confirmé

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 065
    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 065
    Points : 4 229
    Points
    4 229
    Par défaut
    Oui mais l'interceptor risque de faire ça pour toutes les requêtes, ce qui n'est pas mon but, surtout que ça obscurcie le fonctionnement, si quelqu'un d'autre arrive sur l'application sans en être au courant il risque de pété un cable 😂
    Tu veux éviter de faire plusieurs appels de web services s'il n'a toujours pas répondu? Justement j'utilise le mot clé share qui évite ça.

  11. #11
    Membre expert
    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
    Points : 3 004
    Points
    3 004
    Par défaut
    et bien dans un tutoriel écrit par un mec brillant , il propose de vérifier l'url dans l'interceptor pour les filtrer avec ceux destiné à l'api

    bout de code à mettre dans l'interceptor :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
         ...
        const isApiUrl = request.url.startsWith(environment.urlApi + '/' + environment.pathApi);    
        if (isApiUrl) {    
          ...
          ...
    alors qu'est ce tu penses de ça ? hein ?



    et sinon, oui, bien vu avec le share

  12. #12
    Expert confirmé

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 065
    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 065
    Points : 4 229
    Points
    4 229
    Par défaut
    wè ça va vite être le bordel XD, ça reste une possibilité au cas où

  13. #13
    Expert confirmé

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 065
    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 065
    Points : 4 229
    Points
    4 229
    Par défaut
    On m'a proposé ce genre de solution aussi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
      private refDatas: Observable<RefData[]>;
      getAllRefDatas(): Observable<RefData[]> {
     
        if (!this.refDatas) {
          this.refDatas = this.httpClient.get<RefData[]>(`${this.baseUrl}api/RefDatas`).pipe(shareReplay(1));
        }
        return this.refDatas;
      }

  14. #14
    Membre éprouvé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Janvier 2019
    Messages
    707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2019
    Messages : 707
    Points : 1 030
    Points
    1 030
    Par défaut
    oui, en effet !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     private refDatas: Observable<RefData[]>;
      getAllRefDatas(): Observable<RefData[]> {
     
        if (!this.refDatas) {
          this.refDatas = this.httpClient.get<RefData[]>(`${this.baseUrl}api/RefDatas`).pipe(shareReplay(1));
        }
        return this.refDatas;
      }

+ 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