NodeJS #2
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++
NodeJS étant mono-thread, il faut éviter de l'utiliser pour des tâches qui font un usage intensif du CPU
According to indeed.com Node jobs are growing faster than other languages
Selon Google Trends
En tous cas, eux l'utilisent !
+ Netflix, Uber, Linked In, ...
Premier essai : Page "mon compte"
Développement de la même chose en Java en parallèle (minimiser le risque).
Performance
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)
<?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)
Télécharger l'installeur sur https://nodejs.org
(ou alors brew install, apt-get, ...)
node -v
npm -v
read–eval–print loop
exercice
// 1) Créer un fichier helloworld.js
// 2) Faire en sorte qu'il affiche "Hello World"
// en éxecutant `node helloworld.js`
Gestionnaire de paquets NodeJS
(www.npmjs.com)
# ----------- 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
# ----------- 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
{
"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
package.json (2)
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)
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
// 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
// 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";
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
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.
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
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();
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
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)
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.
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)
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...
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.
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
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é
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
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