Animée par Charles Jacquin
Sommaire :
- Introduction
- Node.js core
- Serveur web
- Communication avec une base de donnée
- Communication en temps réel avec socket.io
- Test et deploiement
INTRODUCTION
Historique
- Créé par Ryan Dahl en 2009
- Sponsorisé par Joyent (cloud)
- Construit a partir de la VM de Chromium v8
- Inspiré par Ruby
Installation
Rendez vous sur le site officiel et suivez les instructions.
Pour Ubuntu il existe un PPA.
Node Package Manager
Node.js est fournis avec npm, un gestionnaire de paquet.
- équivalent de gem pour Ruby
- équivalent de maven pour Java
npm install <nom_du_module> #installation dans le repertoire courant
npm install <nom_du_module> -g #installation globale
Package.json
Le fichier package.json se trouve à la racine du projet.
Permet de définir de quels modules depend notre application
npm init #initialisation du fichier package.json
{
"name": "myApp",
"version": "0.0.1",
"description": "A wonderfull app",
"main": "index.js",
"scripts": {
"prestart": "npm update",
"start": "node server.js",
"test": "mocha"
},
"author": "Me <me@myCorp.org> (https://github.com/me)",
"license": "MIT",
"dependencies": {
"express": "*",
"lodash": "*",
"mongoose": "*"
},
"devDependencies": {
"should": "*",
"mocha": "*",
"supertest": "*",
}
}
Npm en detail
- plus de 135 000 packages
- plus d'un milliard de téléchargement par mois
Npm en chiffre :
https://www.npmjs.com/ est un moteur de recherche.
npm search <nom_du_module>
#retourne la liste des module correspondant à la recherche
npm install <nom_du_module> --save
#installation locale et mise à jour des dependencies
npm install <nom_du_module> --save--dev
#installation locale et mise à jour des devDependencies
Du JavaScript éxécuté sur le serveur
Deux choses :
Node utilise v8 le moteur JavaScript de chromium.
Non bloquant.
V8
Moteur Javascript de Chrome
Compilation "Just In Time"
Non bloquant I/O
Le JavaScript est construit autour
de la notion d' événement.
Le roi et ses servants
La même chose en Java
Un peu de code
function doSyncCall(data){
data++;
return data;
}
var data = 1;
console.log(doSyncCall(data));
function doAsyncCall(data,callback){
data++;
callback(data);
}
var data = 1;
doAsyncCall(data, newData => {
console.log(newData);
});
Traitement synchrone
Traitement asynchrone
Gestion des erreurs
Gestion des erreurs
Pour un traitement synchrone
function doSyncCall(data){
if(typeof data !== 'number'){
throw new Error('1st param must be a number');
}else{
return data++;
}
}
var data = 1;
try{
console.log(doSyncCall(data));
}catch(err){
console.log(err);
}
Gestion des erreurs
Les try catch ne servent à rien pour les traitements asynchrone.
function doAsyncCall(data,callback){
if(typeof data !== 'number'){
callback(new Error('1st param must be a number'));
}else{
data++;
callback(null,data);
}
}
var data = 1;
doAsyncCall(data, (err, newData) => {
if(err){
console.log(err.message);
}else{
console.log(newData);
}
});
Le premier paramètre du callback sera toujours l'objet d'erreur
Le deuxième contient la valeur de retour de la fonction
Pyramid of doom
function doAsyncCall(data,callback){
data++;
callback(data);
}
var data = 1;
doAsyncCall(data,function(firstData){
doAsyncCall(firstdata,function(secondData){
doAsyncCall(secondData,function(thirdData){
doAsyncCall(thirdData,function(fourthData){
doAsyncCall(fourthData,function(fifthData){
doAsyncCall(fifthData,function(finalData){
//do something with finalData
});
});
});
});
});
});
DOOM
Les promises
function doAsyncCall(data){
return new Promise((resolve,reject) => {
if(typeof data !== 'number'){
reject(new Error('error !!!'));
}else{
resolve(data++);
}
})
}
var data = 1;
doAsyncCall(data)
.then((newData) => {
console.log(newData); //affiche 2
})
.catch(function(err){
console.error(err);
});
Permettent de limiter la taille de la pyramide.
Avant la version 0.12, il fallait utiliser une librairie tierce comme q ou bluebird.
Les promises sont natives dans ECMA6 et sont implémentées dans la version 0.12 de Node.js
Chainer des promises
function doAsyncCall(data){
return new Promise((resolve,reject) => {
setTimeout(() => {
if(typeof data !== 'number'){
reject(new Error('error !!!'));
}else{
resolve(data++);
}
}, 30)
})
}
var data = 1;
doAsyncCall(data)
.then(newData => {
return doAsyncCall(newData);
})
.then(newData => doAsyncCall(newData)
.then(finalData => {
console.log(finalData) //affiche 3
})
.catch(function(err){
console.error(err);
});
En parallèle
function doAsyncCall(data){
return new Promise((resolve,reject) => {
setTimeout(() => {
if(typeof data !== 'number'){
reject(new Error('error !!!'));
}else{
resolve(data++);
}
}, 30)
})
}
const data = 1;
const anOtherData = 2;
Promise.all([
doAsyncCall(data),
doAsyncCall(anOtherData),
anOtherPromise
]).then(function(data){
//data est un tableaux avec 3 entrées
}).catch(function(err){
});
Node.js Core
Les objets globaux
Global
Dans le browser est declaré dans le scope global
var foo = 'bar';
Dans node, le scope de foo serait le scope du module courant.
Déclare une variable globale.
global.foo ='bar';
Les objets globaux
console
Le même objet que dans le browser
__filename
Le fichier courant
__dirname
Le répertoire courant
Les objets globaux
setTimeout() et clearTimeout()
setInterval() et clearInterval()
Fonctionne comme dans le browser
Les modules de base
Node.js contient de base un certain nombre de paquet.
- fs
- path
- http, https
- ...
Importer un module
Le mot clef "require" permet de récupérer un module.
var fs = require('fs');
fs.readFile('package.json', (err,data) => {
if(err){
console.log('error',err);
}else{
console.log('success',data);
}
});
var pkg = require('./package');
console.log(pkg);
ou un fichier
require.main renvoie le fichier principal de l'application.
Gestion du cache
Les modules sont mis en cache.
Pour recharger le module il faut manipuler require.cache.
require('fs'); //load module
require('fs'); //from cache
delete require.cache.fs
require('fs'); //load module
Exporter un module
L'objet module, nous permet d'exporter un objet.
module.exports = {
findAll(){
},
create(){
},
remove(){
},
update(){
}
}
dao.js
var dao = require('./dao');
dao.findAll();
index.js
L'objet ainsi exporté est utilisable dans les autres fichiers de notre application.
Manipuler des fichiers
Le module fs, permet la manipulation de fichier.
Simples "wrapper" autour des fonctions standard UNIX.
fs : méthodes asynchrones
-
fs.mkdir()
-
fs.readFile()
-
fs.rename()
-
fs.unlink()
-
...
const fs = require('fs');
fs.mkdir('./foo', err => {
})
fs.rename('./foo/bar.txt','./foo/toto.txt', err => {
})
fs.writefile('./foo/bar.txt', data, err => {
})
fs.readfile('./foo/bar.txt', { encoding: 'utf8' }, err => {
})
fs : méthodes synchrones
-
fs.mkdirSync()
-
fs.readFileSync()
-
fs.renameSync()
-
fs.unlinkSync()
-
...
var fs = require('fs'),
fileContent;
try{
fileContent = fs.readfileSync('./foo/bar.txt')
}catch(err){
console.log(err);
}
Toutes ces méthodes existent aussi en version synchrone.
Pour des raisons de performances toujours privilégier les méthodes asynchrones.
fs-promise
Les mêmes méthodes que le module fs mais retournant des promises
const fs = require('fs-promise');
fs.readFile('./log.tkt', { encoding: 'utf8' })
.then(fileContent => {
console.log(fileContent);
})
.catch(err => {
console.error(err)
});
Pour les amateurs de promise !!!
npm i fs-promise -S
http : appel http
Le module http va entre autres nous permettre d'effectuer des requêtes HTTP.
var http = require('http');
module.exports = {
getPosts: function(){
return new Promise((resolve,reject) => {
http.get({
host: 'myWebservice.org',
path: '/posts'
}, response => {
// Continuously update stream with data
var body = '';
response.on('data', d => {
body += d;
});
response.on('end', () => {
resolve(JSON.parse(body));
});
});
})
}
};
isomorphic-fetch
Ce module est une implémentation pour node de la méthode fetch du browser.
const fetch = require('isomorphic-fetch');
module.exports = {
getPosts(){
return fetch('http://www.mywebservice.org/post')
.then(response => response.json())
}
};
npm i fs-promise -S
path
-
path.normalize()
-
path.join()
-
path.resolve()
-
path.dirname()
-
...
var path = require('path');
path.normalize('/foo/bar//baz/..')
//return /foo/bar/baz/'
path.resolve('/foo/bar', './baz')
// return /foo/bar/baz
Le module path permet de manipuler des chemin (absolu ou relatif).
util
-
util.inspect()
-
util.isArray()
-
util.inherit()
-
util.deprecate()
-
...
const util = require('util');
util.inspect({name: 'foo'});
// toString
util.isArray(['foo','bar']);
//return true
util.isDate('foo');
//return false
Le module util contient des méthodes utilitaires.
EventEmitter
Dans Node, beaucoup de modules sont capable d'émettre et d'écouter des évenements.
Ces modules sont des instances de la classe events.EventEmitter.
Comme par exemple les module fs et http.
EventEmitter : les méthodes
Toutes les instances de la classe EventEmitter héritent de ces méthodes :
- addEventListener()
- on()
- once()
- emit()
- removeListener()
- removeAllListener()
Les modules héritant de cette classe peuvent ainsi notifier le reste de l'application d'un changement d'état.
EventEmitter : Utilisation
const util = require('util');
const EventEmitter = require('events').EventEmitter;
class MyStream extends EventEmitter {
constructor() {
super();
}
write(data) {
this.emit('data', data);
}
}
const stream = new MyStream();
stream.on('data', data => {
console.log(`Received data: ${data}`);
});
stream.write('It works!'); // Received data: 'It works!'
L'objet global process
process est une instance de EventEmitter.
Cet objet va nous permettre de définir ou récupérer les variables d’environnement.
De maniére générale cet objet permet de gérer le processus courant :
- évènement (exit...)
- exception
Publier un package sur npm
- un répértoire contenant du code source et un fichier package.json complet.
- une url Git définie dans le fichier package.json
Un package npm est :
Publier un package sur npm
Il ne reste ensuite plus que deux opérations.
S'authentifier
npm adduser
Publier
#Dans le repertoire du package
npm publish
Serveur web
Mise en place d'un serveur http
le package http, sert également à mettre en place un serveur http.
const http = require('http');
const url = require('url');
const server = http.createServer((req, res) => {
const route = url.parse(req.url).pathname;
console.log(route);
res.writeHead(200);
res.end('Hello world');
});
server.listen(8080);
Gestion des routes
const http = require('http');
const url = require('url');
const server = http.createServer((req, res) => {
const route = url.parse(req.url).pathname;
console.log(page);
res.writeHead(200, {"Content-Type": "text/plain"});
switch(route){
case '/':
res.write('Welcome home !!!');
break;
case '/contact':
res.write('Contact us');
break;
default:
res.write('404');
break;
}
});
server.listen(8080);
Querystring
const http = require('http');
const url = require('url');
const querystring = require('querystring');
const server = http.createServer((req, res) => {
const route = url.parse(req.url).pathname;
const params = querystring.parse(url.parse(req.url).query);
res.writeHead(200, {'Content-Type': 'application/json'});
switch(route){
case '/posts':
if(params.title){
//do something
}else{
//do something else
}
break;
default:
res.write('404');
break;
}
});
server.listen(8080);
remarque ?
C'est légèrement verbeux !!!
Vite un framework
Heureusement , l'écosystème Node.js est déjà riche en frameworks et CMS
Frameworks :
CMS :
Express est à la base de tous ces outils (sauf ghost).
Express
Minimaliste, flexible
Framework standard
Fonctionne avec plusieurs moteur de template :
Très pratique pour réaliser des api REST.
- jade
- ejs
- ...
Express : Mise en place
const express = require('express');
const app = express();
const sendHello = (req, res) => {
res.send('Hello, World!');
};
app.get('/', sendHello);
app.listen(3000);
npm install express --save
Hello World !!!
Express : Routes dynamiques
const express = require('express');
const app = express();
app.get('/users/:id', (req, res) => {
console.log(req.params.id);
res.end(req.params.id);
});
app.listen(3000);
Nous pouvons egalement spécifier des routes dynamiques.
Il sera ensuite très facile de récuperer la valeur du paramètre.
Express : renvoyer du html
const express = require('express');
const app = express();
const html = `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Hello</title>
</head>
<body>
<p>Hello World</p>
</body>
</html>`;
app.get('/', (req, res) => {
res.setHeader('Content-Type', 'text/html');
res.send(html);
});
app.listen(3000);
Nous pouvons également renvoyer directement le contenu d'un fichier.
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.setHeader('Content-Type', 'text/html');
res.sendFile(__dirname + '/index.html');
});
app.listen(3000);
Express : le templating
Express nous permet d'utiliser un certains nombre de moteur de template.
- jade
- ejs
- ...
Comportement similaire à du php.
Express : ejs
npm install ejs --save
Embeded JavaScript
const app = require('express')();
const ejs = require('ejs');
app.set('view engine', 'ejs');
app.get('/profile', (req, res) => {
const user = {
email: 'foo@bar.org',
username: 'Mr Foo'
};
res.render('profile', {user});
});
app.listen(3000);
<!doctype html>
<html>
<head>
<title>
Profile
<%= user.username %>
</title>
</head>
<body>
<h1>
<%= user.username %>
</h1>
<div>
<a href="mailto:<%= user.email %>">Contact</a>
</div>
</body>
</html>
Les templates doivent se trouver dans le repertoire views.
./views/profile.ejs
./index.js
Boucles et conditions
const app = require('express')();
app.get('/profile', (req, res) => {
var posts = [
{
title: 'premier post',
content: 'du contenu'
},
{
title: 'deuxième post',
content: 'encore du contenu'
}
];
res.render('blog', {posts posts});
});
app.listen(3000);
<!doctype html>
<html>
<head>
<title>
Blog
</title>
</head>
<body>
<section>
<% posts.forEach(function(post){ %>
<article>
<h1>
<%= post.title %>
</h1>
<p>
<%= post.content %>
</p>
</article>
<% }) %>
</section>
</body>
</html>
./views/blog.ejs
./index.js
Include
<footer>
i'am a footer
</footer>
<!doctype html>
<html>
<head>
<title>
Blog
</title>
</head>
<body>
<%- partial('header') %>
<main>
<!-- some content -->
</main>
<%- partial('footer') %>
</body>
</html>
./views/blog.ejs
./views/footer.ejs
<header>
i'am on top
</header>
./views/header.ejs
Express et les middlewares
middleware ???
Petits bouts de code qui réalisent des actions diverses.
Les middlewares traitent les requetes http et s'enchainent en se passant le contenu de la requête.
- session
- body parser
- json web token
- ...
Body-parser
Parse le contenu des requêtes http.
npm install body-parser --save
const app = require('express')();
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use((req, res, next) => {
res.setHeader('Content-Type', 'application/json')
console.log(req.body);
next();
});
app.post('/post',(req,res) =>{
//faire quelque chose avec req.body
});
app.listen(3000);
Les sessions
npm install express-session --save
const app = require('express')();
const session = require('express-session');
app.use(session({ secret: 'my-secret', cookie: { maxAge: 60000 }}));
app.use((req, res, next) => {
var sess = req.session
if (sess.views) {
sess.views++;
res.setHeader('Content-Type', 'text/html');
res.write('<p>views: ' + sess.views + '</p>');
res.write('<p>expires in: ' + (sess.cookie.maxAge / 1000) + 's</p>');
res.end();
} else {
sess.views = 1;
res.end('welcome to the session demo. refresh!');
}
});
app.listen(3000);
Permet de manipuler les cookies.
Compression (gzip)
npm install compression --save
const app = require('express')();
const compression = require('compression');
app.use(compression({
filter(req, res) {
if (req.headers['x-no-compression']) {
// don't compress responses with this request header
return false
}
// fallback to standard filter function
return compression.filter(req, res)
}
}))
app.listen(3000);
Permet la compression gzip de la page pour un envoi plus rapide au navigateur.
Servir des fichiers statiques
npm install serve-static --save
const app = require('express')();
const serveStatic = require('serve-static');
app.use(serveStatic('public/ftp', { index: ['index.html', 'index.htm'] }));
app.listen(3000);
permet de renvoyer des fichiers statiques contenus dans un dossier.
CRUD
var app = require('express')();
app.route('/api/posts')
.all((req, res, next) => {
// sera executée avant toutes les autres
// sorte de middleware spécifique à la route
})
.get((req, res) => {
res.json([]);
})
.post((req, res) => {
// create a post
})
app.route('/api/posts/:id')
.get((req, res) => {
res.json({});
})
.put((req, res) => {
// update the post
})
.delete((req, res) => {
// remove the post
})
Servir une singlePage Application
const app = require('express')();
const session = require('express-session');
//... your middleware
//... your api routes
app.get('*', (req, res, err) => {
res.sendfile(`${__dirname}/public/index.html`);
})
app.listen(3000);
Gestion des erreurs
const app = require('express')();
const session = require('express-session');
//... your middleware
//... your routes
app.use((req, res, err) => {
console.error(err);
res.status(err.status);
res.json(err);
})
app.listen(3000);
Communication avec une base de données no-sql
En informatique, NoSQL (Not only SQL en anglais) désigne une catégorie de systèmes de gestion de base de données (SGBD) qui n'est plus fondée sur l'architecture classique des bases relationnelles. L'unité logique n'y est plus la table, et les données ne sont en général pas manipulées avec SQL.
Wikipédia
MongoDB
Installer mongoDB http://www.mongodb.org/downloads
{
"_id": ObjectId("4efa8d2b7d284dad101e4bc7"),
"Nom": "DUMONT",
"Prénom": "Jean",
"Âge": 43
}
Des clés peuvent être ajoutées à tout moment "à la volée", sans reconfiguration de la base.
MongoDB VS SQL
On ne parle pas de table mais de collection.
Une collection contient des documents.
Un document est l'équivalent d'un enregistrement.
Pas de schéma, les documents peuvent avoir une structure différente au sein d'une même collection.
Tous les documents possèdent un attribut _id.
Mongoose
O.R.M. pour node.js et mongoDB.
- Définition de schéma
- fonction de validation
- relations
- hooks
Propose une API simple.
npm install --save mongoose
Connexion
const mongoose = require('mongoose')
mongoose.Promise = Promise
module.exports.connectDatabase = uri => {
return new Promise((resolve, reject) => {
mongoose.connection
.on('error', error => reject(error))
.on('close', () => console.log('connection closed'))
.once('open', () => resolve(mongoose.connections[0]))
mongoose.connect(uri)
})
}
Schema : les types
- String
- Number
- Date
- Buffer
- Boolean
- Mixed
- ObjectId
- Array
Les types autorisés par mongoose sont :
Schéma
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
email: {
type: String,
unique: true,
required: 'email is required'
},
age: {
type: Number
},
username: {
type: String,
unique: true
},
hobbies: {
type: Array
},
createdAt: {
type: Date,
default: Date.now()
},
password: {
type: String,
unique: true,
required: 'password is required'
}
});
module.exports = mongoose.model('User', UserSchema);
CRUD : create
const mongoose = require('mongoose');
const User = mongoose.model('User');
//Persister une entité en base
const user = new User({
email: 'dummy@email.com',
password: 'dummyPassword'
})
user.save()
.then(data => {
console.log('user created');
})
.catch(err => {
console.error(err);
})
CRUD : retrieve
const mongoose = require('mongoose');
const User = mongoose.model('User');
//recuperer tous les enregistrements
User.find()
.then(users => {
console.log('users: ', users);
})
.catch(err => {
console.error(err);
})
const mongoose = require('mongoose');
const User = mongoose.model('User');
User.find({ email : 'dummy@email.com' })
.then(users => {
console.log('users: ', users);
})
.catch(err => {
console.error(err);
})
CRUD : retrieve one
const mongoose = require('mongoose');
const User = mongoose.model('User');
User.findOne({ email: 'dummy@email.com' })
.then(user => {
console.log('user: ', user);
})
.catch(err => {
console.error(err);
})
CRUD : update
const mongoose = require('mongoose');
const User = mongoose.model('User');
User.update({ email: 'dummy@email.com' },{ username : 'foo' })
.then(data => {
console.log('data: ', data);
})
.catch(err => {
console.error(err);
})
CRUD : delete
const mongoose = require('mongoose');
const User = mongoose.model('User');
//recuperer tous les enregistrements
User.remove({ email: 'dummy@email.com' })
.then(() => {
console.log('user removed');
})
.catch(err => {
console.error(err);
})
Requête complexe
User.find()
.where('firstname').equals('foo')
.where('age').gt(17).lt(66)
.where('hobbies').in(['reading', 'code'])
.limit(10)
.sort('-age')
.select('firstname email')
.then(data => {
})
.catch(err => {
});
Hooks
const mongoose = require('mongoose'),
const Schema = mongoose.Schema,
const UserSchema = new Schema({
...
});
UserSchema.pre('save',() => {
});
UserSchema.pre('update', () => {
});
module.exports = mongoose.model('User',UserSchema);
Relations
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const PostSchema = new Schema({
...
comments: [{
type: Schema.ObjectId,
ref: 'Comments'
}],
author: {
type: Schema.ObjectId,
ref: 'User'
}
});
module.exports = mongoose.model('User',PostSchema);
Relations: query
var mongoose = require('mongoose'),
Post = mongoose.model('Post');
Post.findOne({ title: 'anAwesomePost' })
.populate('comments')
.then(posts => {
})
Communication en temps réel avec socket.io
Socket.io
Permet de mettre en place une communication "real time".
npm install socket.io --save
Fonctionne même avec des vieux browsers (pré HTML5).
Web-socket ?
Web-socket Vs Ajax
Avec AJAX le client demande et le serveur répond.
Avec les web-sockets, le serveur peut "push" vers le client sans requête préalable.
Socket.io: les technos
Afin de supporter un très large eventail de browser socket.io utilise les technologies suivante coté client :
- Websocket
- Adobe flash socket
- AJAX long polling
- ...
Du coup la plupart des browsers sont supporté même ie 5 ( sisi :) ).
Avec Express
const app = require('express')();
const http = require('http').Server(app);
const io = require('socket.io')(http);
app.get('/', (req, res) => {
res.sendfile('index.html');
});
io.on('connection', socket => {
console.log('a user connected');
});
http.listen(3000, () => {
console.log('listening on *:3000');
});
Socket.io : le client
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Socket.io</title>
</head>
<body>
<h1>Communication avec socket.io !</h1>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:8080');
</script>
</body>
</html>
Le fichier html servi par le serveur.
socket.io.js est servi automatiquement.
Socket.io : communication
io.sockets.on('connection', socket => {
socket.emit('message', 'Vous êtes bien connecté !');
});
var socket = io.connect('http://localhost:8080');
socket.on('message', function(message) {
console.log('new message ',message);
})
Le serveur
Le client
Socket.io : Hello world
io.sockets.on('connection', socket => {
socket.on('hello', message => {
console.log(message);
});
});
var socket = io.connect('http://localhost:8080');
$('#hello').click(function () {
socket.emit('hello', 'Hello World');
})
Le serveur
Le client
<button id="hello">Hello world</button>
Socket.io : Plusieurs clients
socket.emit envoie seulement le message au client courant.
Pour envoyer le message à tous les clients connectés il faut utiliser socket.broadcast().
Socket.io : Hello world à plusieurs
io.sockets.on('connection', socket => {
socket.on('hello', message => {
socket.broadcast.emit('hello',message);
});
});
var socket = io.connect('http://localhost:8080');
$('#hello').click(function () {
socket.emit('hello', 'Hello World');
})
socket.on('hello',function(message){
console.log(message);
})
Le serveur
Le client
<button id="hello">Hello world</button>
Variable de session
Afin d'identifier facilement nos clients, nous allons pouvoir utiliser des variables de sessions.
io.sockets.on('connection', socket => {
socket.on('register', username => {
socket.username = username;
});
});
Socket.io : Namespace (room)
const chat = io
.of('/chat')
.on('connection', socket => {
socket.emit('message','Welcome to the chat');
});
var news = io
.of('/news')
.on('connection', socket => {
socket.emit('lastnews', { news: 'lorem ipsum' });
});
var chat = io.connect('http://localhost:8080/chat'),
news = io.connect('http://localhost:8080/news');
chat.on('connect', function (message) {
console.log(message);
});
news.on('lastnews', function (message) {
console.log(message);
});
Tester son aplication
Les modules
Mocha est le framework de test que nous allons utiliser.
Supertest va nous permetrre de tester notre api REST.
Should est la bibliothèque d'assertion.
Should.js
npm install should --save--dev
const should = require('should');
const user = {
name: 'Heisenberg',
hobbies: ['cooking', 'chemistry']
};
user.should.have.property('name', 'tj');
user.should.have.property('hobbies').with.lengthOf(2);
Simple librairie d'assertion.
Mocha.js
Les tests se trouvent dans le repertoire test.
Le fichier principal se nomme test.js.
Reprenez la structure de votre application pour vos tests.
npm i mocha -D
Mocha : hooks
describe('my tests', () => {
before(() => {
// runs before all tests in this block
})
after(() => {
// runs after all tests in this block
})
beforeEach(() => {
// runs before each test in this block
})
afterEach(() => {
// runs after each test in this block
})
// test cases
})
Mocha : test
const should = require('should');
const thingz = ['foo','bar'];
describe('thingz', () => {
it('should have 2 elements', () => {
thingz.length.should.be(2);
})
})
const should = require('should');
describe('main tests', () => {
describe('nested tests', () => {
it('should test something', () => {
})
})
})
Lancer les tests
mocha --recursive
Mocha + Supertest + express
const request = require('supertest');
const should = require('should');
const app = require('../app').app;
describe('addition', () => {
it('should return a post', done => {
request(app)
.get('/api/post/1')
.expect(200)
.end((err, res) => {
should.not.exist(err);
res.data.should.have.property('content');
done();
});
});
});
Supertest nous permet de tester notre api rest codée avec express.
The End
Réalisé par Charles Jacquin
Formation Node.js
By AdapTeach
Formation Node.js
Formation Node.js
- 1,525