Angular async local storage

Publié le

J’ai développé un module de stockage local asynchrone pour Angular.

Pourquoi ce module ?

Contrairement à React, Angular est un framework complet pour construire une application, avec tous les modules nécessaires directement intégrés (AJAX, routing, etc.). Le seul aspect qui est laissé à votre charge, comme dans la plupart des outils, c’est le stockage local.

Quasiment toute application aura besoin au moins d’un peu de stockage local, ne serait-ce que pour stocker les paramètres de l’utilisateur et souvent un JSON Web Token.

Si vous utilisez un outil comme Ionic, des APIs supplémentaires seront mises à votre disposition, passant généralement par le stockage local natif des mobiles ou tablettes. Mais si vous n’avez pas besoin ou ne voulez pas vous lancer dans Ionic, et rester sur une application web classique seulement avec Angular, vous serez obligé/e de passer par les APIs JavaScript native.

Il en existe deux :

L’API localStorage est simple à utiliser mais synchrone. Cela signifie que si vous l’utilisez trop fréquemment, votre app va commencer à freezer par moment.

L’API IndexedDB est asynchrone et performante, mais c’est un enfer à utiliser. Vous tomberez vite dans le « callbacks hell », l’API ne supportant pas encore les Promises.

Mozilla a réalisé une super librairie, localForage : une API simple calquée sur le localStorage natif, mais en interne stocké de façon asynchrone grâce à IndexedDB pour que cela soit performant. Mais elle est écrite en ES5, et c’est donc compliqué de l’intégrer dans Angular.

Notre module se base sur la même idée que localForage, mais en ES6/ES2015 et encapsulé dans des Observables RxJS pour s’harmoniser avec les autres modules Angular qui les utilisent aussi.

Utilisation du module

Installation via npm :

npm install @ngx-pwa/local-storage

Si vous utilisez Angular >= 6, passez à l’étape suivante. Sinon, intégrez ensuite le module AsyncLocalStorage dans le module racine de votre application. Il fonctionne comme le module Http, en fournissant un service global à toute l’app. In ne faut pas donc le ré-importer dans vos sous-modules.

import { LocalStorageModule } from '@ngx-pwa/local-storage';

@NgModule({
  imports: [
    BrowserModule,
    LocalStorageModule,
    ...
  ]
  ...
})
export class AppModule {}

Vous n’avez plus ensuite qu’à injecter le service là où vous en avez besoin :

import { LocalStorage } from '@ngx-pwa/local-storage';

@Injectable()
export class YourService {

  public constructor(protected localStorage: LocalStorage) {}

  public ngOnInit() {

    this.localStorage.setItem('lang', 'fr').subscribe(() => {
      // Done
    });

  }

}

API

L’API se calque sur celle du localStorage natif, à la différence qu’elle est asynchone via les Observables RxJS.

Enregistrer des données

Il est peu probable que des erreurs surviennent avec le stockage local, mais dans une application, vous devriez toujours intercepter toute erreur potentielle.

Vous n’avez pas besoin de vous désinscrire des observables : ils s’auto-terminent (comme ceux du module Http).

this.localStorage.setItem('color', 'red').subscribe(() => {
  // Done
}, () => {
  // Error
});

Vous pouvez stocker n’importe quelle valeur, sans vous occuper de stringifier.

this.localStorage.setItem('user', { firstName: 'Henri', lastName: 'Bergson' })
  .subscribe(() => {}, () => {});

Pour supprimer un élément :

this.localStorage.removeItem('user').subscribe(() => {}, () => {});

Pour supprimer tous les éléments :

this.localStorage.clear().subscribe(() => {}, () => {});

Lire des données

Ne pas trouver un élément n’est pas une erreur, cela réussit mais retourne null.

this.localStorage.getItem('notexisting').subscribe((data) => {
  data; // null
}, () => {
  // Not called
});

Pensez donc à vérifier la donnée, car elle peut avoir été supprimée du stockage local.

this.localStorage.getItem('user').subscribe((user) => {
  if (user != null) {
    user.firstName; // 'Henri'
  }
}, () => {});

Comme n’importe quelle donnée peut être enregistrée, vous devez typer manuellement :

this.localStorage.getItem('color').subscribe((color: string) => {
  color; // 'red'
}, () => {});

Support et changelog

Cet article n’est qu’une introduction. Pour plus de détails, consultez la page Github du module.

Devenez un Pro!

Cet article vous a aidé ? Et vous voulez soutenir mes contributions open source (avec notamment un outil utilisé par 600 000 développeurs) ? Faites-vous une faveur à vous-même : Schematics Pro est un outil d’automatisation de code pour Angular, React, Vue et tous les autres frameworks JavaScript, qui vous fait gagner en productivité et vous aide à vous assurer du suivi des bonnes pratiques.

En savoir plus sur Schematics Pro

Découvrez ma formation Angular