Sauver des données en Javascript sans base de données

Sauver des données en Javascript sans base de données
Sauver des données en Javascript sans base de données

Cette article est la traduction Française de l’article Saving Data in JavaScript Without a Database, écrit par Andrew Healey.

Vous venez d’écrire un excellent code en JavaScript. Mais lorsque le processus en cours s’arrête, ou que l’utilisateur est actualisé, toutes ces belles données disparaissent dans le vide.

Cela t’est déjà arrivé ?

Lors d’un prototypage, ou du travail sur de petits projets, il peut être utile de gérer un état sans recourir à une solution de base de données qui n’a pas été conçue pour la création que vous essayez de faire.

Nous allons explorer certaines options que j’aurai aimé savoir quand j’ai commencé à bricoler sur le Web. Nous regarderons en JS via le navigateur et Node.js en back-end.
Puis nous examinerons également certaines bases de données légères qui utilisent le système de fichiers local.

Node.js

En premier lieu, JSON sérialise vos données et les enregistre sur disque. Les MDN Docs contiennent un excellent article si vous n’avez jamais travaillé avec JSON.

const fs = require('fs');

const users = {
    'Bob': {
        age: 25,
        language: 'Python'
    },
    'Alice': {
        age: 36,
        language: 'Haskell'
    }
}

fs.writeFile('users.json', JSON.stringify(users), (err) => {  
    // Catch this!
    if (err) throw err;

    console.log('Users saved!');
});

Nous avons créé notre objet utilisateurs, l’avons converti en JSON avec JSON.stringify et appelé fs.writeFile. Nous avons transmis un nom de fichier, nos données sérialisées et une flèche servant de rappel à exécuter à la fin de l’opération d’écriture. Votre programme continuera à exécuter du code entre-temps.

Vous pouvez également utiliser cette méthode pour écrire des données sérialisées normales en transmettant tout ce qui peut être converti en chaîne. Si vous stockez des données texte, vous trouverez fs.appendFile utile. Il utilise une API presque identique mais envoie les données à la fin du fichier, en conservant le contenu existant.

Il existe une option synchrone, fs.writeFileSync, mais elle n’est pas recommandée, car votre programme ne répondra pas jusqu’à la fin de l’opération d’écriture. En JavaScript, vous devriez viser à ne jamais bloquer les choses.

Si vous traitez avec des fichiers CSV, accédez au projet node-csv, testé et éprouvé.
Chargeons ces utilisateurs dans notre programme avec fs.readFile.

fs.readFile('user.json', (err, data) => {
    // Catch this!
    if (err) throw err;

    const loadedUsers = JSON.parse(data);
    console.log(loadedUsers);
});

Bases de données légères

SQLite utilise un fichier local comme base de données – et est l’un de mes logiciels préférés dans le monde. Cela permet à bon nombre de mes plus petits projets d’exister avec peu de maintenance et peu de déploiements.

Voici quelques faits sur SQLite :

  • Le projet contient 711 fois plus de code de test et de scripts de test que d’autres codes.
  • Les développeurs s’engagent à le rendre compatible en amont d’au moins 2050.
  • Il est utilisé dans les avions, sur Android et vous avez probablement interagi avec lui d’une manière ou d’une autre pour vous rendre à cet article aujourd’hui.

Dans Node.js, nous utilisons couramment le package npm sqlite3.
J’utiliserai du code du modèle hello-sqlite de Glitch, avec lequel vous pourrez jouer et remixer sans pour autant avoir de compte.

// hello-sqlite
var fs = require('fs');
var dbFile = './.data/sqlite.db'; // Our database file
var exists = fs.existsSync(dbFile); // Sync is okay since we're booting up
var sqlite3 = require('sqlite3').verbose(); // For long stack traces
var db = new sqlite3.Database(dbFile);

Grâce à cet objet db, nous pouvons interagir avec notre base de données locale comme nous le ferions via une connexion à une base de données externe.
Nous pouvons créer des tables :

db.run('CREATE TABLE Dreams (dream TEXT)');

Insérer des données (avec gestion des erreurs).

db.run('INSERT INTO Dreams (dream) VALUES (?)', ['Well tested code'], function(err) {
  if (err) {
    console.error(err);
  } else {
    console.log('Dream saved!');
    }
});

Sélectionnez ces données en retour.

db.all('SELECT * from Dreams', function(err, rows) {
  console.log(JSON.stringify(rows));
});

Vous voudrez peut-être envisager de sérialiser certaines de vos requêtes de base de données. Chaque commande de la fonction serialize() est assurée de terminer son exécution avant le début de la suivante. La documentation de sqlite3 est vaste. Surveillez les types de données SQLite, car ils peuvent être légèrement différents des autres BDD.

Si même SQLite vous semble trop coûteux pour votre projet, considérez lowdb (également remixable sur Glitch). lowdb est passionnant car c’est une petite base de données JSON locale optimisée par Lodash (supporte Node, Electron et le navigateur). Non seulement cela fonctionne-t-il comme un wrapper pour les fichiers JSON sur le back-end, il fournit également une API qui encapsule localStorage dans le navigateur.

De leurs exemples :

import low from 'lowdb'
import LocalStorage from 'lowdb/adapters/LocalStorage'

const adapter = new LocalStorage('db')
const db = low(adapter)

db.defaults({ posts: [] })
  .write()

// Data is automatically saved to localStorage
db.get('posts')
  .push({ title: 'lowdb' })
  .write()

Browser

Cela nous amène au début. window.localStorage est la solution moderne pour stocker des données dans des cookies HTTP – ce que MDN ne recommande plus pour stocker des choses.

Interagissons avec eux maintenant. Si vous êtes sur le bureau, ouvrez votre console de développement (F12 sur Chrome) et voyez ce que DEV stocke pour vous :

for (const thing in localStorage) {
  console.log(thing, localStorage.getItem(thing))
}

//Example of one thing:
//pusherTransportTL {"timestamp":1559581571665,"transport":"ws","latency":543}

Nous avons vu comment lowdb interagissait avec localStorage, mais pour nos petits projets, il est probablement plus facile de communiquer directement avec l’API. Comme ça :

// As a script, or in console
localStorage.setItem('Author', 'Andrew') // returns undefined
localStorage.getItem('Author') // returns "Andrew"
localStorage.getItem('Unset key') // returns null

Cela devient encore plus facile: vous pouvez le traiter comme un objet. Bien que, MDN recommande l’API sur ce raccourci.

console.log(localStorage['Author']); // prints "Andrew"

Si vous ne voulez pas stocker les données sur l’ordinateur de l’utilisateur pour toujours (ce qui peut être effacé avec localStorage.clear() ), vous pouvez être intéressé par sessionStorage qui a une API presque identique et ne stocke que des données pendant que l’utilisateur est sur la page.