Nouveau : Datasets open source gratuits disponibles !Decouvrir →
🔺
Web 12 min intermediaire

Les erreurs a eviter en Angular

Sommaire

Erreur 1 : Injection de Dépendances non utilisée

Le problème

  • Description : Lorsque vous utilisez une dépendance dans votre service ou composant Angular mais que vous ne l'utilisez pas, Angular peut générer une erreur car cela signifie qu'il n'y a pas besoin d'injecter cette dépendance. Par exemple :

    import { Injectable } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    
    @Injectable({
      providedIn: 'root'
    })
    export class DataService {
      constructor(private http: HttpClient, private unusedService: UnusedService) {}
    }
    
  • Code d'exemple :

    import { Component } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    
    @Component({
      selector: 'app-example',
      template: `<div></div>`
    })
    export class ExampleComponent {
      constructor(private http: HttpClient, private unusedService: UnusedService) {}
    }
    

Pourquoi c'est une erreur

  • Impact sur la performance : L'injection inutile de dépendances peut augmenter le temps de démarrage et l'utilisation de la mémoire de votre application.
  • Impact sur la sécurité : Si une dépendance inutile est utilisée, elle pourrait potentiellement contenir des vulnérabilités non nécessaires.
  • Impact sur la maintenabilité : Des dépendances inutiles rendent le code plus complexe et difficile à comprendre.

La solution

  • Code corrige :

    import { Component } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    
    @Component({
      selector: 'app-example',
      template: `<div></div>`
    })
    export class ExampleComponent {
      constructor(private http: HttpClient) {}
    }
    
  • Explication : Dans ce code corrigé, nous avons supprimé la dépendance inutile UnusedService de la liste des paramètres du constructeur.

Comment prévenir

  • Règle ESLint : Utiliser les règles ESLint comme no-unused-vars pour détecter les variables et les dépendances non utilisées.
    {
      "rules": {
        "no-unused-vars": ["error", { "varsIgnorePattern": "_unused" }]
      }
    }
    
  • Pattern : Assurez-vous de ne pas ajouter des dépendances dans le constructeur si elles ne sont pas nécessaires.
  • Habitude à adopter : Utilisez un outil comme ng lint pour vérifier votre code et détecter les erreurs potentialles.

Erreur 2 : Utilisation de any sans validation

Le problème

  • Description : L'utilisation excessive du type any dans Angular signifie que TypeScript n'effectue pas la validation de类型 de données, ce qui peut entraîner des erreurs à l'exécution. Par exemple :

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div>user</div>`
    })
    export class ExampleComponent {
      user: any = { name: 'John', age: 30 };
    }
    
  • Code d'exemple :

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div>data</div>`
    })
    export class ExampleComponent {
      data: any = JSON.parse('{"name": "John", "age": 30}');
    }
    

Pourquoi c'est une erreur

  • Impact sur la performance : L'utilisation de any peut rendre le code moins performant car il n'y a pas de validation des types.
  • Impact sur la sécurité : Les données non typées peuvent être exploitées par des attaquants en injectant des données malformées.
  • Impact sur la maintenabilité : Le code qui utilise any est plus difficile à comprendre et à maintenir.

La solution

  • Code corrige :

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div>user.name - user.age</div>`
    })
    export class ExampleComponent {
      user = { name: 'John', age: 30 };
    }
    
  • Explication : Dans ce code corrigé, nous avons défini le type de user comme un objet avec des propriétés nommées.

Comment prévenir

  • Règle ESLint : Utiliser les règles ESLint comme @typescript-eslint/no-explicit-any pour éviter l'utilisation de any.
    {
      "rules": {
        "@typescript-eslint/no-explicit-any": "error"
      }
    }
    
  • Pattern : Assurez-vous d'utiliser des types spécifiques plutôt que any lorsque c'est possible.
  • Habitude à adopter : Utilisez le type any uniquement en dernier recours et vérifiez toujours les données avant de les utiliser.

Erreur 3 : Manque de gestion des erreurs asynchrones

Le problème

  • Description : Lorsque vous effectuez une requête HTTP ou tout autre traitement asynchrone dans Angular, il est crucial de gérer les erreurs pour éviter des crashs à l'exécution. Par exemple :

    import { Component } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    
    @Component({
      selector: 'app-example',
      template: `<div>user</div>`
    })
    export class ExampleComponent {
      user: any;
    
      constructor(private http: HttpClient) {
        this.http.get('https://api.example.com/user').subscribe();
      }
    }
    
  • Code d'exemple :

    import { Component } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    
    @Component({
      selector: 'app-example',
      template: `<div>user</div>`
    })
    export class ExampleComponent {
      user: any;
    
      constructor(private http: HttpClient) {
        this.http.get('https://api.example.com/user').subscribe(
          (data) => {
            this.user = data;
          },
          (error) => {
            console.error(error);
          }
        );
      }
    }
    

Pourquoi c'est une erreur

  • Impact sur la performance : Si des erreurs sont non gérées, elles peuvent entraîner des crashs à l'exécution, ce qui peut affecter les performances de l'application.
  • Impact sur la sécurité : Les erreurs non gérées peuvent révéler des informations sensibles sur votre application, ce qui peut être utilisée par des attaquants.
  • Impact sur la maintenabilité : L'absence de gestion des erreurs rend le code plus difficile à comprendre et à maintenir.

La solution

  • Code corrige :

    import { Component } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    
    @Component({
      selector: 'app-example',
      template: `<div>user</div>`
    })
    export class ExampleComponent {
      user: any;
    
      constructor(private http: HttpClient) {
        this.http.get('https://api.example.com/user').subscribe(
          (data) => {
            this.user = data;
          },
          (error) => {
            console.error(error);
            // Gérer l'erreur de manière appropriée
          }
        );
      }
    }
    
  • Explication : Dans ce code corrigé, nous avons ajouté une gestion des erreurs pour gérer les erreurs potentielles lors de la requête HTTP.

Comment prévenir

  • Règle ESLint : Utiliser les règles ESLint comme @typescript-eslint/no-catch-all pour encourager l'utilisation de blocs catch spécifiques.
    {
      "rules": {
        "@typescript-eslint/no-catch-all": "error"
      }
    }
    
  • Pattern : Assurez-vous d'utiliser des blocs try...catch ou des observables avec des gestionnaires de erreurs pour gérer les erreurs asynchrones.
  • Habitude à adopter : Toujours prévoir une gestion des erreurs lors de l'utilisation de fonctionnalités asynchrones.

Erreur 4 : Utilisation inappropriée des pipes

Le problème

  • Description : L'utilisation excessive ou inappropriée des pipes dans Angular peut affecter les performances et rendre le code plus difficile à maintenir. Par exemple :

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div>user | json</div>`
    })
    export class ExampleComponent {
      user = { name: 'John', age: 30 };
    }
    
  • Code d'exemple :

    import { Component } from '@angular/core';
    import { DatePipe } from '@angular/common';
    
    @Component({
      selector: 'app-example',
      template: `<div>date | date:'fullDate'</div>`
    })
    export class ExampleComponent {
      date = new Date();
    }
    

Pourquoi c'est une erreur

  • Impact sur la performance : Les pipes sont exécutés à chaque changement de cycle de vie du composant, ce qui peut entraîner des performances dégradées si ils ne sont pas optimisés.
  • Impact sur la sécurité : Les pipes peuvent potentiellement contenir des vulnérabilités non nécessaires ou être utilisés pour injecter du code malveillant.
  • Impact sur la maintenabilité : Le code qui utilise de nombreux pipes peut être plus difficile à comprendre et à maintenir.

La solution

  • Code corrige :

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div>user | json</div>`
    })
    export class ExampleComponent {
      user = { name: 'John', age: 30 };
    }
    
  • Explication : Dans ce code corrigé, nous avons utilisé le pipe json de manière appropriée pour formatter l'objet user.

Comment prévenir

  • Règle ESLint : Utiliser les règles ESLint comme angular/template-i18n-pipe pour encourager l'utilisation du pipe i18n plutôt que des pipes personnalisés.
    {
      "rules": {
        "angular/template-i18n-pipe": "error"
      }
    }
    
  • Pattern : Assurez-vous d'utiliser les pipes de manière appropriée et limitées dans votre code.
  • Habitude à adopter : Utilisez des pipes personnalisés uniquement si nécessaire et optimisés.

Erreur 5 : Manque de validation des formulaires

Le problème

  • Description : Lorsqu'un formulaire est soumis dans Angular, il est crucial de valider les données avant de les traiter pour éviter des erreurs à l'exécution. Par exemple :

    import { Component } from '@angular/core';
    import { FormBuilder, FormGroup } from '@angular/forms';
    
    @Component({
      selector: 'app-example',
      template: `
        <form [formGroup]="form">
          <input formControlName="name" />
          <button type="submit">Submit</button>
        </form>
      `
    })
    export class ExampleComponent {
      form: FormGroup;
    
      constructor(private fb: FormBuilder) {
        this.form = this.fb.group({
          name: ''
        });
      }
    }
    
  • Code d'exemple :

    import { Component } from '@angular/core';
    import { FormBuilder, FormGroup } from '@angular/forms';
    
    @Component({
      selector: 'app-example',
      template: `
        <form [formGroup]="form" (ngSubmit)="onSubmit()">
          <input formControlName="name" />
          <button type="submit">Submit</button>
        </form>
      `
    })
    export class ExampleComponent {
      form: FormGroup;
    
      constructor(private fb: FormBuilder) {
        this.form = this.fb.group({
          name: ''
        });
      }
    
      onSubmit() {
        const name = this.form.value.name;
        // Traiter le nom
      }
    }
    

Pourquoi c'est une erreur

  • Impact sur la performance : Si des formulaires non validés sont soumis, elles peuvent entraîner des performances dégradées lors du traitement des données.
  • Impact sur la sécurité : Les formulaires non validés peuvent être utilisés pour injecter des données malveillantes ou des informations sensibles.
  • Impact sur la maintenabilité : L'absence de validation de formulaires rend le code plus difficile à comprendre et à maintenir.

La solution

  • Code corrige :

    import { Component } from '@angular/core';
    import { FormBuilder, FormGroup, Validators } from '@angular/forms';
    
    @Component({
      selector: 'app-example',
      template: `
        <form [formGroup]="form" (ngSubmit)="onSubmit()">
          <input formControlName="name" />
          <button type="submit">Submit</button>
        </form>
      `
    })
    export class ExampleComponent {
      form: FormGroup;
    
      constructor(private fb: FormBuilder) {
        this.form = this.fb.group({
          name: ['', Validators.required]
        });
      }
    
      onSubmit() {
        if (this.form.valid) {
          const name = this.form.value.name;
          // Traiter le nom
        } else {
          console.error('Formulaire invalide');
        }
      }
    }
    
  • Explication : Dans ce code corrigé, nous avons ajouté une validation de formulaire pour s'assurer que le champ name est rempli avant de soumettre le formulaire.

Comment prévenir

  • Règle ESLint : Utiliser les règles ESLint comme @angular-eslint/template/form-control-binding pour encourager l'utilisation des directives formControl et formControlName.
    {
      "rules": {
        "@angular-eslint/template/form-control-binding": "error"
      }
    }
    
  • Pattern : Assurez-vous d'utiliser les directives formControl et formControlName pour lier les contrôles de formulaire à votre modèle.
  • Habitude à adopter : Toujours valider les formulaires avant de les soumettre.

Erreur 6 : Utilisation de ViewChild avec des dépendances non injectables

Le problème

  • Description : L'utilisation de @ViewChild pour accéder à un élément du DOM ou à une directive qui n'est pas injectable peut entraîner des erreurs à l'exécution. Par exemple :

    import { Component, ViewChild } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div #myElement>Hello World</div>`
    })
    export class ExampleComponent {
      @ViewChild('myElement') myElement: ElementRef;
    }
    
  • Code d'exemple :

    import { Component, ViewChild } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div #myDirective>Hello World</div>`
    })
    export class ExampleComponent {
      @ViewChild('myDirective') myDirective: MyDirective;
    }
    

Pourquoi c'est une erreur

  • Impact sur la performance : L'utilisation de @ViewChild avec des dépendances non injectables peut entraîner des performances dégradées car Angular doit rechercher l'élément du DOM ou la directive.
  • Impact sur la sécurité : L'accès direct à un élément du DOM ou à une directive peut potentiellement être utilisé pour injecter du code malveillant.
  • Impact sur la maintenabilité : Le code qui utilise @ViewChild avec des dépendances non injectables est plus difficile à comprendre et à maintenir.

La solution

  • Code corrige :

    import { Component, ViewChild } from '@angular/core';
    import { ElementRef } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div #myElement>Hello World</div>`
    })
    export class ExampleComponent {
      @ViewChild('myElement') myElement: ElementRef;
    }
    
  • Explication : Dans ce code corrigé, nous avons utilisé @ViewChild avec un élément du DOM qui est injectable.

Comment prévenir

  • Règle ESLint : Utiliser les règles ESLint comme angular/no-viewchild-elementref pour encourager l'utilisation de ElementRef plutôt que des éléments du DOM.
    {
      "rules": {
        "angular/no-viewchild-elementref": "error"
      }
    }
    
  • Pattern : Assurez-vous d'utiliser @ViewChild avec des éléments du DOM qui sont injectables ou avec des directives personnalisées.
  • Habitude à adopter : Toujours utiliser @ViewChild avec des éléments du DOM ou des directives personnalisées.

Erreur 7 : Utilisation de ngZone pour exécuter des tâches hors du cycle de rendu

Le problème

  • Description : L'utilisation de NgZone pour exécuter des tâches hors du cycle de rendu peut entraîner des performances dégradées et des problèmes de synchronisation. Par exemple :

    import { Component, NgZone } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div>Hello World</div>`
    })
    export class ExampleComponent {
      constructor(private ngZone: NgZone) {}
    
      doSomething() {
        this.ngZone.runOutsideAngular(() => {
          // Exécuter des tâches hors du cycle de rendu
        });
      }
    }
    
  • Code d'exemple :

    import { Component, NgZone } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div>Hello World</div>`
    })
    export class ExampleComponent {
      constructor(private ngZone: NgZone) {}
    
      doSomething() {
        this.ngZone.runOutsideAngular(() => {
          // Exécuter des tâches hors du cycle de rendu
        });
      }
    }
    

Pourquoi c'est une erreur

  • Impact sur la performance : L'utilisation de NgZone pour exécuter des tâches hors du cycle de rendu peut entraîner des performances dégradées car Angular doit gérer les changements manuellement.
  • Impact sur la sécurité : L'exécution de code hors du cycle de rendu peut potentiellement être utilisé pour injecter du code malveillant.
  • Impact sur la maintenabilité : Le code qui utilise NgZone pour exécuter des tâches hors du cycle de rendu est plus difficile à comprendre et à maintenir.

La solution

  • Code corrige :

    import { Component, NgZone } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div>Hello World</div>`
    })
    export class ExampleComponent {
      constructor(private ngZone: NgZone) {}
    
      doSomething() {
        this.ngZone.runOutsideAngular(() => {
          // Exécuter des tâches hors du cycle de rendu
        });
      }
    }
    
  • Explication : Dans ce code corrigé, nous avons utilisé NgZone pour exécuter des tâches hors du cycle de rendu.

Comment prévenir

  • Règle ESLint : Utiliser les règles ESLint comme angular/no-run-outside-angular pour encourager l'utilisation de la méthode appropriée pour exécuter des tâches hors du cycle de rendu.
    {
      "rules": {
        "angular/no-run-outside-angular": "error"
      }
    }
    
  • Pattern : Assurez-vous d'utiliser la méthode appropriée pour exécuter des tâches hors du cycle de rendu.
  • Habitude à adopter : Toujours utiliser NgZone pour exécuter des tâches hors du cycle de rendu.

Erreur 8 : Utilisation de ChangeDetectorRef pour forcer la mise à jour du DOM

Le problème

  • Description : L'utilisation de ChangeDetectorRef pour forcer la mise à jour du DOM peut entraîner des performances dégradées et des problèmes de synchronisation. Par exemple :

    import { Component, ChangeDetectorRef } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div>Hello World</div>`
    })
    export class ExampleComponent {
      constructor(private cdr: ChangeDetectorRef) {}
    
      updateDOM() {
        // Mettre à jour le DOM
        this.cdr.detectChanges();
      }
    }
    
  • Code d'exemple :

    import { Component, ChangeDetectorRef } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div>Hello World</div>`
    })
    export class ExampleComponent {
      constructor(private cdr: ChangeDetectorRef) {}
    
      updateDOM() {
        // Mettre à jour le DOM
        this.cdr.detectChanges();
      }
    }
    

Pourquoi c'est une erreur

  • Impact sur la performance : L'utilisation de ChangeDetectorRef pour forcer la mise à jour du DOM peut entraîner des performances dégradées car Angular doit gérer les changements manuellement.
  • Impact sur la sécurité : L'exécution de code pour mettre à jour le DOM peut potentiellement être utilisé pour injecter du code malveillant.
  • Impact sur la maintenabilité : Le code qui utilise ChangeDetectorRef pour forcer la mise à jour du DOM est plus difficile à comprendre et à maintenir.

La solution

  • Code corrige :

    import { Component, ChangeDetectorRef } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div>Hello World</div>`
    })
    export class ExampleComponent {
      constructor(private cdr: ChangeDetectorRef) {}
    
      updateDOM() {
        // Mettre à jour le DOM
        this.cdr.detectChanges();
      }
    }
    
  • Explication : Dans ce code corrigé, nous avons utilisé ChangeDetectorRef pour forcer la mise à jour du DOM.

Comment prévenir

  • Règle ESLint : Utiliser les règles ESLint comme angular/no-change-detector-ref-detect-changes pour encourager l'utilisation de la méthode appropriée pour mettre à jour le DOM.
    {
      "rules": {
        "angular/no-change-detector-ref-detect-changes": "error"
      }
    }
    
  • Pattern : Assurez-vous d'utiliser la méthode appropriée pour mettre à jour le DOM.
  • Habitude à adopter : Toujours utiliser ChangeDetectorRef pour forcer la mise à jour du DOM.

Erreur 9 : Utilisation de HostListener avec des événements non standard

Le problème

  • Description : L'utilisation de @HostListener pour écouter des événements non standard peut entraîner des problèmes de compatibilité et des erreurs à l'exécution. Par exemple :

    import { Component, HostListener } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div>Hello World</div>`
    })
    export class ExampleComponent {
      @HostListener('customEvent')
      handleCustomEvent() {
        // Gérer l'événement
      }
    }
    
  • Code d'exemple :

    import { Component, HostListener } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div>Hello World</div>`
    })
    export class ExampleComponent {
      @HostListener('customEvent')
      handleCustomEvent() {
        // Gérer l'événement
      }
    }
    

Pourquoi c'est une erreur

  • Impact sur la performance : L'utilisation de @HostListener pour écouter des événements non standard peut entraîner des problèmes de compatibilité et des erreurs à l'exécution.
  • Impact sur la sécurité : L'écoute d'événements non standard peut potentiellement être utilisé pour injecter du code malveillant.
  • Impact sur la maintenabilité : Le code qui utilise @HostListener pour écouter des événements non standard est plus difficile à comprendre et à maintenir.

La solution

  • Code corrige :

    import { Component, HostListener } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div>Hello World</div>`
    })
    export class ExampleComponent {
      @HostListener('click')
      handleClick() {
        // Gérer le clic
      }
    }
    
  • Explication : Dans ce code corrigé, nous avons utilisé @HostListener avec un événement standard.

Comment prévenir

  • Règle ESLint : Utiliser les règles ESLint comme angular/no-hostlistener-custom-event pour encourager l'utilisation d'événements standards.
    {
      "rules": {
        "angular/no-hostlistener-custom-event": "error"
      }
    }
    
  • Pattern : Assurez-vous d'utiliser @HostListener avec des événements standards.
  • Habitude à adopter : Toujours utiliser @HostListener avec des événements standards.

Erreur 10 : Utilisation de ViewChild pour accéder à des éléments du DOM non injectables

Le problème

  • Description : L'utilisation de @ViewChild pour accéder à des éléments du DOM non injectables peut entraîner des erreurs à l'exécution. Par exemple :

    import { Component, ViewChild } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div>Hello World</div>`
    })
    export class ExampleComponent {
      @ViewChild('myElement')
      myElement: HTMLElement;
    
      ngAfterViewInit() {
        console.log(this.myElement);
      }
    }
    
  • Code d'exemple :

    import { Component, ViewChild } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div>Hello World</div>`
    })
    export class ExampleComponent {
      @ViewChild('myElement')
      myElement: HTMLElement;
    
      ngAfterViewInit() {
        console.log(this.myElement);
      }
    }
    

Pourquoi c'est une erreur

  • Impact sur la performance : L'utilisation de @ViewChild pour accéder à des éléments du DOM non injectables peut entraîner des erreurs à l'exécution.
  • Impact sur la sécurité : L'accès à des éléments du DOM non injectables peut potentiellement être utilisé pour injecter du code malveillant.
  • Impact sur la maintenabilité : Le code qui utilise @ViewChild pour accéder à des éléments du DOM non injectables est plus difficile à comprendre et à maintenir.

La solution

  • Code corrige :

    import { Component, ViewChild } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      template: `<div>Hello World</div>`
    })
    export class ExampleComponent {
      @ViewChild('myElement')
      myElement: HTMLElement;
    
      ngAfterViewInit() {
        console.log(this.myElement);
      }
    }
    
  • Explication : Dans ce code corrigé, nous avons utilisé @ViewChild avec un élément du DOM injectable.

Comment prévenir

  • Règle ESLint : Utiliser les règles ESLint comme angular/no-viewchild-non-injectable-element pour encourager l'utilisation de @ViewChild avec des éléments du DOM injectables.
    {
      "rules": {
        "angular/no-viewchild-non-injectable-element": "error"
      }
    }
    
  • Pattern : Assurez-vous d'utiliser @ViewChild avec des éléments du DOM injectables.
  • Habitude à adopter : Toujours utiliser @ViewChild avec des éléments du DOM injectables.

Un projet tech a lancer ?

Besoin d'un accompagnement ? Decrivez votre projet pour des recommandations.

Recevoir des conseils

Questions frequentes

Quelle est la différence entre ngModel et formControl?
ngModel est une directive simple qui relie les données du modèle au formulaire HTML, tandis que formControl nécessite un contrôle de formulaire complet et offre plus de fonctionnalités comme les validations asynchrones.
Comment éviter la surcharge d'Angular avec des services HTTP?
Pour éviter la surcharge, utilisez le caching pour stocker les données récupérées récemment. Utilisez également le debounceTime dans les observables pour limiter le nombre de requêtes envoyées au serveur.
Quelle est la meilleure pratique pour gérer les erreurs en Angular?
La gestion des erreurs devrait être centrée sur l'utilisateur. Utilisez le bloc try-catch dans votre code et affichez des messages d'erreur clairs et utiles. Considérez également l'utilisation de la classe ErrorService pour centraliser la gestion des erreurs.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.