Fermer

décembre 29, 2025

Récupération de données dans Angular moderne

Récupération de données dans Angular moderne


Découvrez comment la récupération de données a changé dans Angular 21 avec l’API de ressources et l’API httpResource.

Au moment où j’écris cet article, Angular 21.0 a été publié et a changé la façon dont les données doivent être récupérées dans les applications Angular modernes. Habituellement, dans une application Angular, les données proviennent d’une API et peuvent être classées comme suit :

  1. Récupérer des données depuis le serveur
  2. Mutation des données sur le serveur

Dans les applications Angular modernes, il y a deux nouveaux basé sur le signal façons de récupérer des données :

  1. API de ressources
  2. API httpResource

Les deux ressource et httpResource Les API ont le même objectif, mais elles diffèrent dans la manière dont elles effectuent des requêtes HTTP. Le ressource L’API utilise le natif du navigateur aller chercher fonction, tandis que httpResource s’appuie sur Angular Client HTTP service pour exécuter la demande.

Depuis httpResource utilise le module intégré d’Angular Client HTTPil fonctionne automatiquement avec d’autres fonctionnalités angulaires telles que intercepteurs.

Pour approfondir, commençons par créer une interface de modèle qui représente la structure de réponse de l’API.

export interface IProduct{
    id:number; 
    name : string; 
    price : number;
    description?: string;
    cateogry?: string;
}

Vous pouvez maintenant utiliser le ressource API pour récupérer des données, comme indiqué ci-dessous. C’est vraiment aussi simple que cela sous le capot ; il utilise le natif du navigateur aller chercher API pour effectuer la requête HTTP.

   productApiResource = resource({
    loader: async () => {
      return fetch('http://localhost:3000/product').then(
        (res) => res.json() as Promise<IProduct[]>
      );
    },
  });

L’API Resource renvoie un WritableResource et possède des propriétés en lecture seule telles que :

  • valeur
  • statut
  • erreur
  • est en cours de chargement

Outre les propriétés en lecture seule ci-dessus, il possède également un aValeur() fonction pour vérifier si la propriété de valeur de ressource a une valeur ou non.

Vous pouvez utiliser le signal de valeur pour lire les données renvoyées dans un contexte réactif, dans ce cas, un modèle comme indiqué ci-dessous :

<table>
    <tr>
        <th>Id</th>
        <th>Name</th>
        <th>Price</th>
        <th>description</th>
    </tr>
    @for(p of productApiResource.value();track p.id) {
    <tr>
        <td>{{p.id}}</td>
        <td>{{p.name}}</td>
        <td>{{p.price}}</td>
        <td>{{p.description}}</td>
    </tr>
    }
</table>

À l’aide de httpResource, vous pouvez récupérer des données de l’API comme indiqué dans la liste de codes suivante.

productApiResource = httpResource<IProduct[]>(() => ({
    url: `http://localhost:3000/product`,
    method: 'GET'
  }));

Ici, nous transmettons l’URL et la méthode HTTP (GET) pour récupérer les données. Comme l’API Resource, l’API httpResource renvoie une WritableResource et possède des propriétés en lecture seule telles que :

  • valeur
  • statut
  • erreur
  • est en cours de chargement

De la même manière que vous utilisez le ressource API, vous pouvez également utiliser l’API httpResource API dans un contexte réactif, par exemple à l’intérieur du modèle, comme indiqué ci-dessous.

<table>
    <tr>
        <th>Id</th>
        <th>Name</th>
        <th>Price</th>
        <th>description</th>
    </tr>
    @for(p of productApiResource.value();track p.id) {
    <tr>
        <td>{{p.id}}</td>
        <td>{{p.name}}</td>
        <td>{{p.price}}</td>
        <td>{{p.description}}</td>
    </tr>
    }
</table>

Les principaux objectifs des API de ressources et de httpResource sont les suivants, mais elles sont le plus souvent utilisées pour extraire des données du serveur.

  • Récupérer les données de l’API
  • Mettre à jour les données localement
  • Charger une ressource locale de manière asynchrone

Aucune de ces API ne doit être utilisée pour les mutations de serveur. En d’autres termes, évitez de les utiliser pour des opérations HTTP comme POSTE, METTRE ou SUPPRIMER. Ils sont destinés uniquement à OBTENIR demandes. Cependant, supposons que vous disposiez de points de terminaison d’API qui renvoient des données via un POSTE demande sans réellement muter les données sur le serveur. Dans ce cas, vous pouvez également utiliser ces API en toute sécurité à cette fin.

Étant donné que les API de ressources et httpResource renvoient diverses propriétés en lecture seule basées sur des signaux, elles peuvent être lues et suivies dans des contextes réactifs, des effets et des valeurs calculées.

constructor() {
    effect(() => {
      console.log('Product Resource Data has value ', this.productApiResource.hasValue());
      console.log('Product Resource Data ', this.productApiResource.value());
      console.log('Product Resource Staus  ', this.productApiResource.status());
      console.log('Product Resource Error ', this.productApiResource.error());
      console.log('Product Resource is Loading  ', this.productApiResource.isLoading());

    })

  }

  productApiResource = resource({
    loader: async () => {
      return fetch('http://localhost:3000/product').then(
        (res) => res.json() as Promise<IProduct[]>
      );
    },
  });

Angular imprime les valeurs comme ci-dessous :

Les données sur les ressources du produit ont une valeur – faux, un statut – chargement, etc.

Une fois la ressource résolue, les valeurs de ses propriétés sont mises à jour et, comme il s’agit de signaux, les valeurs mises à jour sont automatiquement récupérées dans l’effet.

Les données sur les ressources produit ont une valeur : vrai, tableau 100 ; statut – résolu, etc.

Comme vous pouvez le constater, la valeur du statut passe de loading à resolved. Les deux ressource et httpResource Les API fournissent ces valeurs d’état sous forme de chaînes.

  1. inactif – La ressource n’a aucune requête valide et n’effectuera aucun chargement. Ici, value() est indéfini.
  2. chargement – La ressource charge actuellement une nouvelle valeur. Ici, value() est indéfini.
  3. rechargement – La ressource est en train de recharger la nouvelle valeur. Ici, value() est la valeur précédemment récupérée.
  4. erreur – La ressource n’a pas réussi à charger la valeur. Ici, value() est indéfini.
  5. résolu – La ressource a terminé le chargement. Ici, value() est renvoyé par le chargeur.
  6. locale – La valeur de la ressource a été définie localement par set() ou update().

Vous pouvez également utiliser ces propriétés pour calculer d’autres valeurs. Par exemple, si vous devez calculer le prix total de tous les produits, vous pouvez le faire comme indiqué ci-dessous.

  totalPrice = computed(() => {
    if (this.productApiResource.hasValue()) {
      let products = this.productApiResource.value() || [];
      return products.reduce((sum, product) => sum + product.price, 0);
    }
    return 0;
  });

Vous pouvez utiliser le totalPrice signal calculé sur le modèle :

<h2>Total Price of Product = {{totalPrice()}}</h2>

La même explication s’applique à httpResource de plus, puisqu’il est construit sur ressource.

Parfois, vous devrez peut-être transmettre des paramètres à une ressource. Par exemple, si vous souhaitez récupérer un produit spécifique depuis l’API, vous devrez transmettre son identifiant. Pour soutenir cela, le ressource L’API accepte un argument params facultatif qui vous permet de fournir ces valeurs.

sProduct = signal(1);

  selectedProductApiResource: any = resource({
    params: () => ({ id: this.sProduct() }),
    loader: async ({ params }) => {
      let id = params.id;
      return fetch('http://localhost:3000/product/' + id).then(
        (res) => res.json() as Promise<IProduct>
      );
    },
  });

selectProduct(id: number) {
    this.sProduct.set(id);
  }

Angular suit les paramètres, donc chaque fois qu’un signal utilisé à l’intérieur change, Angular réexécute automatiquement le chargeur de ressources. C’est pourquoi il est recommandé de transmettre les paramètres sous forme de valeurs basées sur un signal via params.

Vous pouvez utiliser le produit sélectionné en utilisant le selectedProductApiResource comme indiqué ci-dessous :

<h2>Selected Product Details</h2>
@if(selectedProductApiResource.hasValue()){
    <div>
        <b>Id:</b> {{selectedProductApiResource.value()?.id}} <br/>
        <b>Name:</b> {{selectedProductApiResource.value()?.name}} <br/>
        <b>Price:</b> {{selectedProductApiResource.value()?.price}} <br/>
        <b>Description:</b> {{selectedProductApiResource.value()?.description}} <br/>
    </div>
}

Vous devez éviter de lire les entrées basées sur le signal directement à l’intérieur du chargeur, car le chargeur lui-même n’est pas suivi. Même si la valeur du signal change, Angular ne réexécutera pas le chargeur. En conséquence, le code ci-dessous sera pas récupérer le produit pour l’ID sélectionné.

  selectedProductApiResource: any = resource({
    loader: async ({ params }) => {
      return fetch('http://localhost:3000/product/' + this.sProduct()).then(
        (res) => res.json() as Promise<IProduct>
      );
    },
  });

L’Angulaire ressource L’API ne gère pas automatiquement les erreurs d’API. Par exemple, si vous demandez un identifiant qui n’existe pas et que l’API renvoie un 404la propriété d’erreur restera indéfinie.

selectedProductApiResource: any = resource({
    params: () => ({ id: this.sProduct() }),
    loader: async ({ params }) => {
      
      let id = 340399 
      return fetch('http://localhost:3000/product/' + id).then(
        (res) => res.json() as Promise<IProduct>
      );
    },
  });

Imprimez ensuite différentes propriétés dans l’effet.

  constructor(){
    effect(() => {
      console.log('selected product data -', this.selectedProductApiResource.value());
      console.log('selected product status -', this.selectedProductApiResource.status());
      console.log('selected product error -', this.selectedProductApiResource.error());
      console.log('selected product is loading -', this.selectedProductApiResource.isLoading());
    });
  }

Comme vous le voyez, l’erreur reste indéfinie et la ressource est résolue avec succès.

erreur de produit sélectionné – non défini, deux fois

Vous devez donc gérer les erreurs d’API séparément et éviter de vous fier à la valeur d’erreur renvoyée par l’API de ressource. Cependant, tout rejet de promesse sera toujours reflété dans le statut d’erreur de la ressource. Pour voir cela en action, générons une erreur de promesse comme indiqué ci-dessous.

selectedProductApiResource: any = resource({
    params: () => ({ id: this.sProduct() }),
    loader: async ({ params }) => {
      
      let id = 340399 
      return Promise.reject(new Error(`Promise rejected for ID: ${params.id}`));
    },
  });

En effet, vous verrez que la valeur d’erreur est définie comme indiqué ci-dessous :

état du produit sélectionné – erreur. erreur de produit sélectionné – erreur – promesse rejetée pour celui-ci...

Une chose importante à retenir est que si une ressource se trouve dans un erreur état et vous essayez de lire son value() propriété, Angular générera une erreur d’exécution. Il est donc toujours préférable de lire la valeur d’une ressource uniquement après avoir vérifié hasValue()comme indiqué ci-dessous.

constructor(){
    effect(() => {
      if(this.selectedProductApiResource.hasValue()){
        console.log('selected product data -', this.selectedProductApiResource.value());
      }
    });
  }

En savoir plus sur l’API httpResource

Le httpResource étend l’API Resource en utilisant HttpClient sous le capot.

  • La httpResource est construite au-dessus de la primitive de ressource.
  • Il utilise HttpClient comme chargeur, tandis que l’API Resource utilise fetch.
  • Il effectue des requêtes HTTP via la pile HTTP d’Angular, il fonctionne donc avec les intercepteurs et les fonctionnalités associées.

Vous pouvez créer une httpResource à l’aide de la fonction httpResource comme indiqué ci-dessous :

  productApiResource = httpResource<IProduct[]>(() => ({
    url: `http://localhost:3000/product`,
    method: 'GET'
  }));

La fonction httpResource crée un Ressource qui récupère les données à l’aide d’une requête HTTP GET et se met automatiquement à jour lorsque l’URL change via des signaux. Il utilise Client HTTPil prend donc en charge les intercepteurs, les outils de test et toutes les fonctionnalités de HttpClient. La réponse est analysée au format JSON par défaut, avec des options telles que httpResource.text() pour une analyse alternative.

Voyons comment vous pouvez utiliser httpResource efficacement pour récupérer des données et les lier à un composant.

La première chose est de créer la httpResource dans un service Angular comme indiqué ci-dessous :

export class ProductService {

  productApiResource = httpResource<IProduct[]>(() => ({
    url: `http://localhost:3000/product`,
    method: 'GET'
  }));

}

Ensuite, dans le composant, lisez le signal de valeur du httpResource à l’intérieur d’un signal calculé, comme indiqué ci-dessous.

@Component(
{...}
)
export class Product {

  productService = inject(ProductService);
  products = computed(() => {
    if (this.productService.productApiResource.hasValue()) {
      return this.productService.productApiResource.value()
    }
    return [];
  });

Sur le modèle, affichez la réponse récupérée comme indiqué ci-dessous.

<table>
    <tr>
        <th>Id</th>
        <th>Name</th>
        <th>Price</th>
        <th>description</th>
    </tr>
    @for(p of products();track p.id) {
    <tr>
        <td>{{p.id}}</td>
        <td>{{p.name}}</td>
        <td>{{p.price}}</td>
        <td>{{p.description}}</td>
        <td><button (click)=" select(p.id)">select</button></td>
    </tr>
    }
</table>

Nous avons ajouté un Sélectionner bouton pour choisir un produit spécifique. Pour prendre en charge cela dans le service :

  • Ajoutez un signal pour stocker l’ID du produit sélectionné.
  • Ajoutez une ressource qui récupère le produit sélectionné en fonction de cet ID.
  public selectedProduct: WritableSignal<number> = signal<number>(1);

   selectedProductApiResource  = httpResource<IProduct>(() => ({
    url: `http://localhost:3000/product/${this.selectedProduct()}`,
    method: 'GET',
  }));


Ensuite, dans le composant, définissez l’ID sélectionné et lisez le produit sélectionné via un signal calculé.

  selectedProduct = computed(() => {
    if (this.productService.selectedProductApiResource.hasValue()) {
      return this.productService.selectedProductApiResource.value()
    }
    return null;
  });

  select(id: number) {
    this.productService.selectedProduct.set(id);
  }

Vous remarquerez peut-être également que, contrairement à une ressource, httpResource suit automatiquement tous les signaux utilisés dans l’URL. Puisque l’ID fait partie de l’URL, chaque fois que l’ID change, httpResource déclenche un nouvel appel d’API. Sur le modèle, le produit sélectionné peut être affiché comme indiqué ci-dessous.

<h2>Selected Product Details</h2>

    <div>
        <b>Id:</b> {{selectedProduct()?.id}} <br/>
        <b>Name:</b> {{selectedProduct()?.name}} <br/>
        <b>Price:</b> {{selectedProduct()?.price}} <br/>
        <b>Description:</b> {{selectedProduct()?.description}} <br/>
    </div>

Voici comment vous pouvez utiliser httpResource pour récupérer des données à partir d’une API et les consommer dans un composant.

Par défaut, httpResource analyse la réponse au format JSON. Pour gérer d’autres types de données, il fournit des méthodes dédiées pour d’autres types de réponses. Ils sont les suivants :

  • httpResource.text récupère les données sous forme de texte brut
  • httpResource.blob récupère comme un blob
  • httpResource.arrayBuffer récupère les données en tant que ArrayBuffer

Par exemple, vous pouvez télécharger un blob d’image à l’aide de httpResource comme indiqué ci-dessous :

imageName: WritableSignal<string> = signal<string>('a.png');
  imageResource = httpResource.blob<any>(() => ({
    url: `http://localhost:3000/product/image/${this.imageName()}`,
    method: 'GET',
    type: 'blob'
  }));

Ensuite, dans le composant, lisez le blob d’image dans le signal calculé.

  productImage = computed(() => {
    if (this.productService.imageResource.hasValue()) {
      let blob = this.productService.imageResource.value();
      console.log('Blob Image ', blob);
      return URL.createObjectURL(blob);
    }
    return null;
  });

Ensuite, dans le modèle, utilisez le signal calculé comme source d’une image :

<img [src]="productImage()" />

Pour les requêtes avancées, l’API httpResource prend en charge un objet de requête avec plusieurs champs. Parmi eux, seule l’URL est obligatoire ; tous les autres champs sont facultatifs.

  • URL
  • méthode
  • corps
  • paramètres
  • en-têtes
  • contexte
  • rapportProgrès
  • avecCredentials
  • transfertCache
  • temps mort
  • Etc.

Bien que l’objet httpResource prenne en charge d’autres verbes, tels que POST, PUT et DELETE, il est conseillé d’utiliser l’API httpResource uniquement pour récupérer des données depuis le backend et non pour effectuer des mutations à l’aide d’autres verbes HTTP.

Résumé

Dans Angular moderne, où la réactivité est alimentée par des signaux, ressource et httpResource doit être utilisé pour récupérer des données à partir des API. Ces deux API, combinées à des vues différées, constituent la base de la création d’applications Angular robustes et modernes.

J’espère que vous avez trouvé cet article utile. Merci d’avoir lu.




Source link