NodeJS basics

NodeJS #2

NodeJS en bref...

  • Créé par Ryan Lienhart Dahl en 2009,
  • Utilise la machine virtuelle V8,
  • Serveur http intégré,
  • Permet de faire du JS côté serveur,
  • Léger et rapide,
  • I/O non bloquants et asynchrone,
  • Single threaded.

V8 JS Engine

V8 JavaScript engine est un moteur JavaScript libre et open source développé par Google au Danemark. Il est notamment utilisé dans les navigateurs Chromium et Google Chrome, ainsi que sur la plateforme node.js.

 

V8 est écrit en C++

Quand utiliser ?

Quand NE PAS

utiliser ?

NodeJS étant mono-thread, il faut éviter de l'utiliser pour des tâches qui font un usage intensif du CPU

Il y a des jobs ?

According to indeed.com Node jobs are growing faster than other languages

Qui s'y intéresse ?

Selon Google Trends

C'est trop jeune pour

de la prod ?

En tous cas, eux l'utilisent !

+ Netflix, Uber, Linked In, ...

What else ?

Premier essai : Page "mon compte"

Développement de la même chose en Java en parallèle (minimiser le risque).

  • Développement 2 fois plus rapide en NodeJS
  • 33% de lignes de code en moins en NodeJS
  • 40% de fichiers en moins en NodeJS

   Performance

  • Deux fois plus de requêtes par seconde en NodeJS.
  • Pages servies 200ms plus vite avec NodeJS.

Paypal aujourd'hui

700 développeurs NodeJS 

80+ apps en production

Kraken open-source (http://krakenjs.com)

The new Wordpress.com

Projet "calypso"

Refonte de l'interface d'admin WP.com en NodeJS, React, ...

https://developer.wordpress.com/calypso/

NodeJS a permis de réaliser un client web mais aussi utilisable sous forme d'app desktop (electron)

NodeJS est monothread

NodeJS est asynchrone

<?php

// Heure actuelle
echo date('h:i:s') . "\n";

// Stoppe pour 10 secondes
sleep(10);

// retour !
echo date('h:i:s') . "\n";

?>

Synchrone (PHP)

// On passe par une fonction de callback
setTimeout(function() {
  console.log("s'affiche après 1 seconde");
}, 1000);

console.log("s'affiche directement");

Asynchrone (JS)

Installation

Télécharger l'installeur sur https://nodejs.org

(ou alors brew install, apt-get, ...)

LTS schedule

Vérifions

node -v
npm -v

REPL

read–eval–print loop

Hello World

exercice

// 1) Créer un fichier helloworld.js
// 2) Faire en sorte qu'il affiche "Hello World"
//    en éxecutant `node helloworld.js`

NPM (modules)

Gestionnaire de paquets NodeJS

(www.npmjs.com)

NPM packages

# ----------- Dans la console

# installation d'un paquet local
npm install <package_name>

# chercher des modules
npm search postgresql

# vérifier l'installation
ls node_modules

# installation d'un paquet global
sudo npm install -g <package_name>

# Mettre à jour les paquets locaux
npm update

# ----------- Dans un fichier .js
const PackageName = require('package_name');

Utiliser des modules

NPM packages

# ----------- Dans la console

# Création du package.json
npm init

# ----------- Dans un fichier .js
exports.printMsg = function() {
  console.log("This is a message from the demo package");
}

# ----------- Publication
// ==> https://docs.npmjs.com/getting-started/publishing-npm-packages

Créer des modules

NPM packages

{
  "name": "my_package",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "ag_dubs",
  "license": "ISC",
  "repository": {
    "type": "git",
    "url": "https://github.com/ashleygwilliams/my_package.git"
  },
  "bugs": {
    "url": "https://github.com/ashleygwilliams/my_package/issues"
  },
  "homepage": "https://github.com/ashleygwilliams/my_package"
}

package.json

NPM packages

package.json (2)

Node modules

exercice

// 1) Dans un nouveau dossier, initialiser un projet NodeJS avec :
//    * le module "lodash",
//    * le module "prompt",

// 2) Dans le prompt, demander d'entrer une phrase
//    * ex: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"

// 3) La console doit retourner le nombre de mots de la phrase
//    * ex: "La phrase contient x mots"

// 4) Faire en sorte que la commande "npm start" lance le script

// BONUS) N'autoriser que les lettres et les caractères espace (exception sinon)

Global objects

setInterval(cb, ms) // Exécute le callback toutes les ms millisecondes
setTimeout(cb, ms) // Exécute le callback après ms millisecondes

require() // Charger des modules
module // Référence au module courant
exports

console

__dirname // Nom du dossier courant du fichier éxécuté
__filename // Nom du fichier courant

process // Process object

Exports

// getset.js

let content;

exports.setContent = function(thing) {
  content = thing;
}

exports.getContent = function() {
  return content;
}

// index.js

const GetSet = require('getset');
GetSet.setContent('truc');
GetSet.getContent(); // ==> truc

exports vs module.exports

// greetings.js
// var exports = module.exports = {};

exports.sayHelloInEnglish = function() {
  return "HELLO";
};

exports.sayHelloInSpanish = function() {
  return "Hola";
};

/* 
 * this line of code re-assigns  
 * module.exports
 */
module.exports = "Bonjour";

Process

Global object

Process object est une instance d'EventEmitter

process.env // Environnement utilisateur
process.argv // CLI arguments
process.arch // Architecture processeur
process.pid // PID
process.version // Node version

process.memoryUsage() // Usage mémoire
process.nextTick(callback[, arg][, ...])
process.send(message[, sendHandle][, callback]) // Send message
process.uptime() // In seconds

https://nodejs.org/api/process.html

Process.nextTick()

Global object

Plus efficace que setTimeout(..., 0);

console.log('start');

process.nextTick(() => {
  console.log('nextTick callback');
});

console.log('scheduled');


// Output:
// start
// scheduled
// nextTick callback

Appeler la fonction au prochain traitement de la pile d'événements.

Events

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', (a) => {
  console.log('an event occurred: ' + a);
});
myEmitter.emit('event', 'a');

// myEmitter.once

https://nodejs.org/api/events.html

Une grande partie de l'API de base Node.js est construit autour d' une architecture événementielle asynchrone

Events

exercice

// 1) Compléter la définition de classe
class Car {

  // 2) Doit émettre un événement "starting" (avec l'heure en argument)
  start() {}

  // 3) Doit émettre un événement "stoping" (sans argument)
  stop() {}

}

const car = new Car();

// 4) Ecouter l'événement "starting" et loguer "starting car at XX:XX"
// 5) L'événement "starting" doit être logué une seule fois (malgré 3x)

// 6) Ecouter l'événement "stoping" et loguer "stoping car"  

car.start();
car.start();
car.start();

car.stop();

File System

const fs = require('fs');

// Async

fs.unlink('/tmp/hello', (err) => {
  if (err) throw err;
  console.log('successfully deleted /tmp/hello');
});

// Sync

const fs = require('fs');

fs.unlinkSync('/tmp/hello');
console.log('successfully deleted /tmp/hello');

https://nodejs.org/api/fs.html

Wrappers synchrones et asynchrones wrappers autour des fonctions standard POSIX

File System

fs.exists('/etc/passwd', (exists) => {
  console.log(exists ? 'it\'s there' : 'no passwd!');
});

Tester l'existence d'un fichier (fs.exists)

fs.readFile('input.txt', function (err, data) {
   if (err) {
       return console.error(err);
   }
   console.log("Asynchronous read: " + data.toString());
});

Lire le contenu d'un fichier (fs.readFile)

File System

Dans le cas d'un readFile par ex, on reçoit un buffer !

Un buffer est un tableau de bits. La classe Buffer possède différentes méthode pour encoder et décoder un buffer.

File System

fs.stat('input.txt', function (err, stats) {   
   // Check file type
   console.log("isFile ? " + stats.isFile());
   console.log("isDirectory ? " + stats.isDirectory());    
});

Des informations sur un fichier (fs.stat)

fs.writeFile('input.txt', 'Simply Easy Learning!',  function(err) {
   if (err) {
       return console.error(err);
   }
   console.log("Data written successfully!");
});

Ecrire dans un fichier (fs.writeFile)

File System

fs.rename(oldPath, newPath, callback) // Renomer un fichier
fs.rmdir(path, callback) // Supprimer un dossier
fs.mkdir(path[, mode], callback) // Créer un dossier
fs.watch(filename[, options][, listener]) // Observer les changements

// https://nodejs.org/api/fs.html

Mais aussi...

File System

exercice

// Grâce à un script NodeJS: 

// 1) Créer un dossier nommé "foo",
// 2) Ajouter un fichier nommé "foo.txt",
// 3) Ecrire une phrase à l'intérieur de ce fichier.

OS

const os = require('os');

os.cpus() // CPU / cores
os.freemem() // Mémoire libre
os.homedir() // Dossier home 
os.networkInterfaces() // Interfaces réseau
os.tmpdir() // Dossier tmp
os.totalmem() // Mémoire globale
os.type() // 'Linux' pour Linux, 'Darwin' pour OS X and 'Windows_NT' pour Windows
os.uptime() // Machine uptime

https://nodejs.org/api/os.html

Informations sur la machine

http

var http = require('http');

var server = http.createServer(function(req, res) {
  res.writeHead(200);
  res.end('Hello World');
});

server.listen(8080);

https://nodejs.org/api/http.html

Serveur web intégré

http

exercice

// Grâce à un script NodeJS: 

1) Lancer un serveur web sur le port 8080
2) Faire en sorte que l'url "http://localhost:8080" affiche "Hello World"
3) Faire en sorte que les urls:
"http://localhost:8080/sum?a=3&b=5" affiche "3+5 = 8"
"http://localhost:8080/sum?a=22&b=5" affiche "22+5 = 27"
...
4) Toutes les autres pages doivent afficher une erreur 404

Mais aussi...

const util = require('util'); // Utilitaires divers
const cluster = require('cluster'); // Cluster de process
const querystring = require('querystring'); // Pour parser les querystrings
const url = require('url'); // Pour parser les URL's

[NODEJS] NodeJS basics (cours 2)

By Julien Herpin

[NODEJS] NodeJS basics (cours 2)

  • 1,002