close

Découverte de l'Api File System de Node.js

#1 Visite de la page web de l'Api File System open

La page ci-dessous correspond au deuxième tuto de présentation de Node.js dédié à la découverte de l'Api File System.

En septembre 2022, je travaille avec la version 16 de node.js. Vous avez la documentaion ici. Je descends pour voir apparaître File System. Je clique sur File System.

Sur cette page (* extrait ci-dessous), je vois qu'il y a trois exemples en début de doc qui montrent les trois façons de travailler avec cette Api File system 😃.

Trois manières de travailler avec l'Api Node.js

Je vois que je peux travailler avec des promises, avec des callbacks, ça c'est asynchrone, et je vois que je peux travailler avec une Api synchrone.

Au début de ce tuto, on va programmer ces trois exemples pour tâter le terrain.

#2 Premier exemple I/O asynchrone avec des promises open

Je clique sur Promise example. Sur la droite du morceau de code de l'exemple, je vois un switch CJS / ESM (* Voir image ci-dessous). CJS veut dire CommonJS Module et ESM veut dire ECMAScript Module. Ceci correspond aux deux standards différents qui sont supportés par Node.js pour la gestion des modules JavaScript. Node.js a commencé avec la gestion CommonJS et a ensuite ajouté la gestion ECMAScript.

CommonJS ou ECMAScript module

Ci-dessous, je vais faire un premier exemple en CommonJS. Je vois que dans ce cas l'exemple propose d'utiliser une fonction auto-invoquée (IIFE Immediately Invoked Function Expression). En argument de l'appel, je vais changer pour mettre ./hello.txt. Je crée ce fichier et j'exécute. Je vois que le fichier ./hello.txt est supprimé.

Maintenant, je vais faire un essai en ECMAScript. Là à priori, je n'ai plus besoin d'une IIFE et je n'ai même pas besoin d'encapsuler mes await dans une fonction déclarée avec async, puisque je suis dans un module JavaScript.

Quand j'exécute ce morceau de code, j'ai un problème (* voir ci-dessous). A priori, il faut que j'ajoute "type" : "module" dans le fichier package.json. Il va donc falloir que je crée ce fichier package.json et je vais le faire en faisant un npm init -y puis je rajoute l'info en question. (* docs.npmjs.com)

Travailler avec les modules ECMAScript
Ajouter type=module dans package.json

J'exécute et je vérifie que ça fonctionne correctement.

#3 Deuxième exemple I/O asynchrone avec des callbacks open

Maintenant, je vais faire le deuxième exemple. Au niveau des modules, je vais travailler directement en ECMAScript en utilisant les callbacks. Evidemment l'inconvénient avec les callbacks est toujours le même. Si vous avez plusieurs appels à faire, vous allez tomber dans l'éternel problème du callback hell.

#4 Troisième exemple I/O synchrone open

Le synchrone, c'est toujours syntaxiquement faisable. Tout dépend de ce que vous faites. Si certains traitements sont trop longs, alors votre application sera bloquée 😬 pendant la durée de ces traitements. Ce n'est pas vraiment conseillé et ce n'est pas dans l'esprit Node.js qui justement vous apporte l'asynchrone. Cependant, cette possibilité est présente.

En tout cas, c'est assez simple de s'y retrouver, car pour un appel synchrone, c'est le même nom qu'en asynchrone avec un Sync de concaténé à la fin de chaque méthode de l'Api. Vous voyez qu'ici, on a concaténé Sync à unlink pour faire unlinkSync.

#5 Donc on va travailler avec les promises open

Maintenant que j'ai fait ces trois exemples, je vais choisir de travailler avec les promises. C'est un choix que j'aurais pu faire directement, mais disons que ça vaut toujours la peine de farfouiller dans la doc.

Maintenant, dans la doc, je m'intéresse à Promise Api. Je descends un peu dans la doc, et je vois une classe fileHandle. Si je regarde rapidement les méthodes qui sont proposées, je me rends compte qu'avec ça, je travaille uniquement sur les fichiers. Je n'ai pas accès à des fonctionnalités de système de fichiers.

Si je clique sur close, c'est là que je vois le rôle du open. C'est original.🙃

L'api promise

Dans l'exemple ci-dessous, un open me renvoie une sorte de descripteur de fichier filehandle. Avec ce descripteur de fichier, j'ai accès à des méthodes. Par exemple, je peux faire un filehandle.read(). Si je parcours la classe, je vois que je peux faire à priori toutes les manips nécessaires sur un fichier. Par contre, il faut penser à fermer le fichier, c'est ce qui est fait dans le programme ci-dessous avec le filehandle?.close(). Le close sera appelé grâce au finally que la promise soit résolue ou rompue. Le point d'interrogation est un ternaire. Le .close() ne sera appelé que si filehandle est évalué à true.

Cette classe FileHandle fait penser à la librairie standard C sous Unix (* Année 1990), sauf que là, on est quand même asynchrone. On peut se mettre sur un open et faire F12 pour atteindre la définition et on a accès à toute la spéc de fs/promises en typescript (* menu Atteindre / Atteindre la définition).

Si je continue de descendre dans la doc, je vois maintenant toute une liste de méthodes avec lesquelles je peux travailler sur le système de fichier et aussi sur les fichiers.

La suite de l'api fspromises

Je vais faire un exemple dans lequel je vais :

  1. Lire le contenu du répertoire courant.
  2. Tester si le fichier package.json existe.
  3. S'il existe alors le lire puis l'afficher à l'écran.
Résultat de l'exécution
Résultat de l'exécution de test-promise.js

Utiliser cette liste d'appel comme on vient de le faire dans cet exemple me parait être la meilleure façon d'utiliser l'Api File System pour les besoins courants.

Si vous débutez, je vous conseille de vous intéresser aussi à l'Api Path et à l'Api Process qui sont des utilitaires incontournables, lorsque l'on programme sous Node.js.