0% ont trouvé ce document utile (0 vote)
5K vues147 pages

Java Script

Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
5K vues147 pages

Java Script

Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
Vous êtes sur la page 1/ 147

JavaScript

Basé sur les slides de Victoria Kirst https://web.stanford.edu/class/cs193x/staff/


JavaScript

● Historiquement permet de programmer des interactions


au sein des navigateurs
○ Interagir : savoir qu’un bouton a été cliqué
○ Afficher : manipuler la page web pour rendre visible
des nouvelles parties
○ Communiquer : envoyer ou recevoir des requêtes
● C’est le seul langage disponible côté navigateur
● Mais est aussi disponible côté serveur via NodeJS
Exemple

<!doctype html>
<html lang="fr">
<head>
<title>Example</title>
<script>
var msg = "hello";
alert(msg);
</script>
</head>
<body>
</body>
</html>
Best practice

<!doctype html>
<html lang="fr">
<head>
<title>Example</title>
<script src="script.js"></script>
</head>
<body>
</body>
</html>
Messages de log

L’instruction qui permet d’afficher des messages de log en


JavaScript est :

script.js

console.log('Hello, world!');
Exécution de JavaScript

Il n’y a pas de "main method"


● Le script est exécuté de haut en bas

Il n’y a pas de compilation par le développeur


● JavaScript est compilé et exécuté à la volée par le
navigateur
Similarités avec Java, C, ...

for-loops:
for (let i = 0; i < 5; i++) { … }
while-loops:
while (notFinished) { … }
comments:
// comment or /* comment */
conditionals (if statements):
if (...) {
...
} else {
...
}
Fonctions

La syntaxe suivante est une des manières de définir une


fonction en JavaScript

function name() {
statement;
statement;
...
}
Exemple
hello();
hello();

function hello() {
console.log('Hello!');
console.log('Welcome to JavaScript');
}

Cela fonctionne car les déclarations de


fonctions sont hoisted : déplacées au
sommet du scope dans lesquelles elles
sont définies
il faut éviter de se reposer sur ce
mécanisme
Variables

Trois façons de déclarer des variables en JS

// Function scope variable


var x = 15;
// Block scope variable
let fruit = 'banana';
// Block scope constant; cannot be reassigned
const isHungry = true;

Le langage est dynamiquement typé


Paramètres de fonctions

function printMessage(message, times) {


for (var i = 0; i < times; i++) {
console.log(message);
}
}

Les paramètres de fonctions ne sont pas déclarés à l’aide de


let, const ou var
Comprendre var

function printMessage(message, times) {


for (var i = 0; i < times; i++) {
console.log(message);
}
console.log('Value of i is ' + i);
}

printMessage('hello', 3);

La valeur de i est accessible hors de


la boucle for car var déclare des
variables avec un scope fonction
Comprendre let

function printMessage(message, times) {


for (let i = 0; i < times; i++) {
console.log(message);
}
console.log('Value of i is ' + i);
}

printMessage('hello', 3);

La valeur de i n’est pas accessible


hors de la boucle for car let déclare
des variables avec un scope block
Comprendre const

const y = 10;
y = 0; // error!
y++; // error!
const list = [1, 2, 3];
list.push(4); // OK
Les variables déclarées avec const ne peuvent
pas être réaffectées
Cependant il reste possible de modifier l’objet
sous jacent
● Ressemble au final de Java
Bonnes pratiques

● Utiliser const partout où vous pouvez

● Si vous avez besoin d’une variable réaffectable, utilisez


let
● N’utilisez pas var.
○ const et let sont maintenant bien supportés par les
browsers
Types

Les variables JS n’ont pas de types, mais leurs valeurs si

Il y a plusieurs types primitifs:


● Boolean : true et false
● Number : tout est de type double (pas d’entiers)
● String: avec 'single' ou "double-quotes"
● Null: null une valeur qui signifie “ceci n’a pas de valeur”
● Undefined: la valeur d’une variable non affectée

Il y a aussi les types Object, comme Array, Date, et même


Function!
Transtypage booléen

Les valeurs non booléennes peuvent être utilisées dans les


instructions de contrôle, elles sont converties en "truthy" ou
"falsy"
○ null, undefined, 0, NaN, '' évaluent à false
○ Les autres valeurs évaluent à true

if (username) {
// username is defined
}
Egalité

== et != font une conversion implicite de type avant


comparaison

'' == '0' // false


'' == 0 // true
0 == '0' // true
NaN == NaN // false
[''] == '' // true
false == undefined // false
false == null // false
null == undefined // true
Opérateurs === et !==

=== et !== sont les véritables opérateurs de comparaison,


toujours les utiliser!

'' === '0' // false


'' === 0 // false
0 === '0' // false
NaN === NaN // still weirdly false
[''] === '' // false
false === undefined // false
false === null // false
null === undefined // false
null et undefined

Quelle différence?
● null est la valeur représentant l’absence de valeur
(comme null en Java)
● undefined est la valeur d’une variable n’ayant pas reçu
de valeur
Tableaux

Les tableaux sont les objets pour définir des listes

// Creates an empty list


const list = [];
const groceries = ['milk', 'cocoa puffs'];
groceries[1] = 'kix';

// For each loop


for (let item of groceries) {
console.log(item);
}
Objets

Collection de paires clé - valeur, peut être utilisé comme une


hashmap
const prices = {};
const scores = {
peach: 100,
mario: 88,
luigi: 91
};
console.log(scores['peach']); // 100
console.log(scores.peach); // 100
scores.peach = 20;
console.log(scores.peach); // 20
Itérer les propriétés d’un objet

Il est possible d’itérer sur les propriétés d’un objet

const scores = {
peach: 100,
mario: 88,
luigi: 91
};

for (let name in scores) {


console.log(name + ':' + scores[name]);
}
Fonctions de premier ordre

En JavaScript, les fonctions sont des objets comme les


autres
var add = function(a, b) {
return a + b;
}

add(2, 2); // 4
Ajout d’une fonction sur un objet

On peut ajouter une fonction dans un objet, this désigne


l’objet receveur
const scores = {
peach: 100,
mario: 88,
luigi: 91,
total: function() {
return this.peach + this.mario + this.luigi;
}
};
Classes ES6
class Person {
constructor(name, age) { ● Le constructeur est
this.name = name; optionnel
this.age = age; ● Tous les attributs et les
}
méthodes sont publics
displayAge() { ● Tous les appels de
console.log(this.age); méthodes et les accès
}
displayName() {
d’attributs se font via
console.log(this.age); this
}
displayAgeAndName() {
this.displayAge();
this.displayName();
}
}

const p = new Person("Joe",1);


Callbacks
Les fonctions peuvent être passées en paramètres d’autres
fonctions
const groceries = ['milk', 'cocoa puffs'];

// For each loop


for (let item of groceries)
console.log(item);

// Callback style
groceries.forEach(function(item) {
console.log(item);
});

// Nerdy callback style (use that!)


groceries.forEach(item => {
console.log(item);
});
Mais que fait forEach?

class Array {
forEach(callback) {
for (let i = 0; i < this.length; i++) {
callback(this[i], i, this);
}
}
}

forEach itère sur tous les éléments du tableau, pour chaque


élément, elle applique la fonction callback (passée en
paramètre de forEach) en lui fournissant en paramètre l’
élément courant forEach calls callback back!
DOM

On accède aux éléments composant la page web en


JavaScript au travers du Document Object Model
<html>
<head>
<title></title>
</head>
<body>
<h1></h1>
<div>
<p></p>
</div>
</body>
</html>
DOM et JavaScript

JavaScript peut :

● examiner les noeuds du DOM pour en inspecter l’état


(ex. voir le texte saisi par un utilisateur)
● editer les attributs des noeuds du DOM (ex. changer le
style d’un élément <h1>)
● ajouter ou supprimer des noeuds du DOM (ex. ajouter
un texte de statut quelque part)
Accéder aux noeuds du DOM

L’accès aux noeuds du DOM se fait via la fonction


querySelector:

document.querySelector('css selector');
● Retourne le premier noeud qui matche la règle CSS

document.querySelectorAll('css selector');
● Retourne tous les éléments qui matchent la règle CSS
Quelques propriétés des noeuds du DOM

Property Description

id la valeur de l’attribut id de l’élément


le HTML entre le noeud ouvrant et fermant de l’
innerHTML
élément vu comme une chaîne de caractères
Le contenu texte d’un noeud ainsi que celui de ses
textContent
descendants
Un objet contenant toute la liste des classes dans
classList
lesquelles l’élément se situe
Créer des éléments dans le DOM

Il est possible de créer des éléments dynamiquement via


createElement et appendChild:

document.createElement(tag string)
element.appendChild(element);

On peut supprimer des éléments via remove

element.remove();
Évènements

EVENT! function onClick()

Click Me!
{...}

Exemple : un élément de page avec lequel on peut


interagir. Quand on clique sur le bouton, un
événement est déclenché. L’utilisateur peut
enregistrer des callbacks sur les événements de son
choix
Envoyer des requêtes

// FAKE HYPOTHETICAL API.


// This is not real a JavaScript function!
const content = loadFromFile('images.txt');

Quelques problèmes avec cette API fictive:


● Ce serait mieux de charger les données de manière
asynchrone sinon l’appel va être bloquant
● Il n’est pas possible de vérifier le statut de la requête.
Quid si la ressource n’existe pas? Si l’on a pas les droits?
L’API Fetch

L’API Fetch comporte une seule fonction, concise et facile à


utiliser

fetch('images.txt');

● fetch prend en paramètre l’URL de la ressource que


vous voulez consulter
● Elle retourne une Promise
● What???
Les Promise
const promise = fetch('images.txt');
promise.then(onSuccess, onFail);

Une promesse peut être dans un des états suivants


● pending: état initial, promesse non-exécutée
● fulfilled: la promesse a été exécutée correctement
● rejected: la promesse a rencontrée une erreur
On attache un gestionnaire à une promesse via .then()

fetch('images.txt').then(response =>
console.log(response.status));
REST
Restful API

Une API web est dite “Restful” si elle a les caractéristiques


suivantes:

- Les requêtes sont envoyées sous forme de requêtes HTTP:


- Méthodes HTTP: GET, POST, PUT, PATCH, DELETE..
- Un Endpoint: http://example.com/api/ressources
- Les requêtes doivent être envoyées avec un
MIME*/Content-type spécifique tel: JSON, XML, HTML, etc.

* Multipurpose Internet Mail Extensions


Contraintes d’une API REST

Une API Restful doit respecter certaines contraintes d’architecture:

1. Archi client-serveur: chacun évolue indépendamment.


2. Serveur sans états (stateless): pas de sessions.
3. Utilisation du cache: le client sait combien de temps il peut
garder les données qu’il reçoit avant expiration.
4. Une interface uniforme: un seul id, contient l’URL des
ressources suivantes..
5. Archi en couches: Réduire la complexité de l’architecture
globale de l’API.
6. Code à la demande: étendre les fonctionnalités du client.
Ressources

En REST tout est resources, on interagit avec les ressources à


travers différents endpoints (URLs):

- http://example.com/products
- http://example.com/products/1
- http://example.com/products/1/description
Action sur les ressources

Pour interagir avec une ressource, il suffit d’utiliser la méthode


HTTP (verbe) adéquate :

- GET http://example.com/products/1 (Récupérer)


- POST http://example.com/products (Créer)
- PUT http://example.com/products/1 (Mettre à jour)
- DELETE http://example.com/products/1 (Effacer)
API Endpoints

API de Twitter

https://developer.twitter.com/en/docs/tweets/post-and-engage/overview
API Endpoints

POST statuses/update
Paramètres des Endpoints

Un endpoint peut accepter un ensemble de paramètres pour


effectuer sa tâche. Ces paramètres peuvent être passés de
trois manières différentes:

- Paramètres dans l’URL.


- Headers dans la requête.
- Corps (body) de la requête.
Paramètres des Endpoints - paramètres dans l’URL
Paramètres des Endpoints - headers de la requête
Paramètres des Endpoints - corps de la requête
Codes d’état HTTP (Status code)

Il existe plus de 40 codes HTTP, chacun ayant une siginification


bien précise. Voici les grandes catégories:

- 1xx: Information (e.g. 100 attente de la suite (continue))


- 2xx: Succès (e.g. 200 tout s’est bien passé (OK))
- 3xx: Redirection (e.g. 301 document déplacé (redirection))
- 4xx: Erreur du client web (e.g. 404 document introuvable)
- 5xx: Erreur du serveur (e.g. 500 Erreur interne)
API Restful et cache (E-tags)

Les E-tags permettent d’implémenter la contrainte de cache


pour une API Restful. Il existe également d’autres méthodes qui
sont l’utilisation des headers Expires et cache-control.
API Restful et cache (E-tags)

Une fois que je connais l’E-tag, je peux à l’avenir demander s’il


a changé ou non en envoyant une requête avec comme header:

If-None-Match: c0947-b1-4d0258df1f625
API Restful et cache (E-tags)
OpenAPI

C’est un ensemble de spécifications permettant de décrire


une API REST.

Cette description peut être comprise aisément à la fois par


les développeurs ainsi que par les ordinateurs.

L’API est décrite sous forme d’un fichier JSON ou YAML.

Un ensemble d’outils permet de facilement convertir ces


fichiers de description en documentation web ou encore en
bibliothèques pour directement utiliser l’API décrite sans
avoir à l’implémenter.
OpenAPI
OpenAPI
NodeJS
NodeJS

- C’est un runtime Javascript écrit en C++.


- Il permet d’interpréter et exécuter du code Javascript.
- Il fournit par défaut un ensemble de bibliothèques pour
interagir avec le système d’exploitation et concevoir des
serveurs Web.

NodeJS API V8 (chrome)


Un ensemble riche de C’est le “moteur” qui
bibliothèques Javascript permet à NodeJS
pour concevoir des d’interpréter et d’exécuter
serveurs Web. du code Javascript
Chrome
Chrome

Console.log(document.getElementById(‘information’));
NodeJS
NodeJS

Console.log(document.getElementById(‘information’));

document WHAT ?!
NodeJS

Console.log(“Hello”);

“Hello”
NodeJS en ligne de commande

Lancer node sans spécifier de fichier en argument le démarre


une boucle REPL (Read-Eval-Print-Loop).

$ node
> let i = 0
undefined
> i++
0
> i
1
NodeJS avec des scripts

NodeJS peut également être utilisé à travers des scripts.


Pour le lancer, il suffit simplement d'exécuter node en
spécifiant le fichier à exécuter en argument.
$ node monscript.js

function hello() {
console.log(“Hello World!”);
}

hello();

monscript.js
NPM: Node Package Manager

Lorsque vous installez node, vous installez également npm.

C’est un outil en ligne de commande qui vous permet de


facilement installer des packages écrits en Javascript et
compatibles avec NodeJS.

Pour rechercher des packages rendez-vous sur


https://npmjs.com
NPM: Pour les nuls...
$ npm init
$ npm install express [--save] [-g]
$ npm uninstall express
$ npm start
$ npm install

package.json
NPM: Pour les nuls...

$ npm start
$ npm test
NPM: Pour les nuls...

$ npm installDb
ExpressJS
ExpressJS

const express = require('express');


const app = express();

// répondre avec hello world quand on reçoit une


requête GET
app.get('/',(req, res) => {
res.send('hello world');
});

app.listen(3000, () => {
console.log("Serveur démarré");
});
app est une instance d’ExpressJS.
Routes

Une route est définie comme suit:


app.method(path, handler)

- method: permet de définir la méthode HTTP de la


requête.
- path: permet de définir le chemin de la ressource
demandée.
- handler: représente la fonction qui va gérer la requête
lors de sa réception.
Handler

Un handler reçoit toujours deux objets en paramètres. Ces


objets sont créés par express est sont spécifiques à chaque
requête reçue.

app.get('/', (req, res) => {


res.send('hello world');
});

res.send() envoie la réponse avec un MIME/Content-type par défaut à “text/html”


Chaîner les Handler

Il est également possible de chaîner les Handlers, pour ce


faire il suffit de spécifier le paramètre “next” et d’y faire
appel.
app.get('/example', (req, res, next) => {
console.log('La réponse sera envoyée par la
fonction suivante...');
next();
}, (req, res) => {
res.send('Hello from B!');
});
Ordre de déclaration des routes

L’ordre de déclaration des routes est important. Toujours


mettre le chemin racine en dernier.
app.get('/products', (req, res) => {
res.send('products list');
});

app.get('/', (req, res) => {


res.send('hello world');
});
Méthodes de l’objet réponse

res.send('hello world');
res.status(404).end();
res.status(404).send('product not found.');
res.json(json_object);
res.redirect(301, 'http://example.com');
Paramètres d’une requête HTTP

Il existe plusieurs méthodes pour récupérer les paramètres


d’une requête HTTP:

// http://localhost:3000/?prenom=john&nom=doe
app.get('/', (req, res) => {
res.send(req.query.prenom);
});
Paramètres d’une requête HTTP

Il existe plusieurs méthodes pour récupérer les paramètres


d’une requête HTTP:

// http://localhost:3000/john/doe
app.get('/:prenom/:nom', (req, res) => {
var prenom = req.params.prenom
res.send('Salut ' + prenom + ’ !’);
});
Headers d’une requête HTTP

Pour récupérer des headers depuis la requête entrante, il


vous suffit de faire appel à la méthode get().
req.get('user-agent');
console.log(req.headers);
Body d’une requête HTTP

Pour récupérer le body de la requête entrante, il vous suffit


d’utiliser l’attribut body de l’objet req.

<form action="login" method="post">


<input type="text" id="email" name="email">
<input type="password" name="password">
<input type="submit" value="Submit">
</form>

app.post('/login', function (req, res) {


res.json(req.body);
});
Données statiques

ExpressJS permet également de transmettre des fichiers


statiques tels des fichiers html, css, js, jpg…
const express = require('express');
const app = express();

app.use(express.static("public"));

app.get('/', (req, res) => {


res.send('hello world');
});
Outils: Supervision

Redémarrer automatiquement le serveur lorsqu’un


changement a été effectué sur un des fichiers du projet.

Différents outils :

● Forever
● nodemon
● pm2
● supervisor
Outils: cURL

C’est un outil qui va vous permettre de faire des requêtes


depuis votre terminal avec les méthodes HTTP que vous
voulez.

$ curl -X GET http://localhost:3000/john/doe

$ curl -X POST http://localhost:3000/john/doe

$ curl -X PUT http://localhost:3000/john/doe

$ curl -X DELETE http://localhost:3000/john/doe


Outils: Postman, insomnia

Si vous préférez utiliser plutôt une interface graphique riche


en fonctionnalités, vous pouvez également utiliser postman
ou encore insomnia.

getpostman.com

insomnia.rest
Outils: Insomnia
Outils: Ngrok

Si vous voulez partager votre localhost avec le reste du


monde, Ngrok vous permet d’avoir une URL publique.

https://ngrok.com
Outils: Ngrok
ExpressJS (suite)
Rappel

const express = require('express');


const app = express();

// répondre avec hello world quand on reçoit une


requête GET
app.get('/',(req, res) => {
res.send('hello world');
});

app.listen(3000, () => {
console.log("Serveur démarré");
});
Rappel

const express = require('express');


const app = express();

// répondre avec hello world quand on reçoit une


requête GET
app.get('/',(req, res) => {
res.send('hello world');
});

app.listen(3000, () => {
console.log("Serveur démarré");
});
Modules

NodeJS permet de charger des modules à travers la


commande require().

Pour créer votre propre module, il faut obligatoirement créer


un fichier javascript (un module = un fichier).

Par défaut, tout est privé dans un module (variable,


fonctions..). Pour qu’une variable ou fonction ne soit pas
privée, il faudra clairement le spécifier.
Modules

Chaque fichier JS possède un objet qui lui est propre nommé


module.

Lorsqu’on fait appel à la fonction require(), c’est l’attribut


exports de l’objet module du fichier JS qu’on import qui
sera retourné. Il est vide par défaut.
module.exports = “Hello World”
module.exports = (req, res) => {
res.send(“Hello World”)
}
Modules

function printHello() {
console.log("Hello")
}

function printWorld() {
console.log("World!")
}

module.exports.printHello = printHello
module.exports.printWorld = printWorld
Modules

Pour require() un module présent dans notre projet, il


faudra contrairement à ce qu’on a vu précédemment,
clairement spécifier le chemin relatif du fichier JS sans son
extension.

require(“./module1/fichier”)

Si on ne spécifie pas le chemin, la fonction require() ira


chercher le module dans le dossier node_modules.
Middleware

Avec ExpressJS, toutes les fonctions qui ont comme


argument la fonction next() ou non sont appelés
middleware.

Nous avions vu ça précedemment avec les handlers pour


gérer les routes, on avait dit qu’on pouvait chaîner les
handlers. Les handlers sont donc des middlewares.
function checkAuth(req, res, next) {
if (req.get("API-KEY")) next()
else res.send("Error: Auth missing")
}
app.get("/", checkAuth, ...)
Middleware: app.use()

Il est également possible de définir des Middleware qui seront exécutés


au début de chaque nouvelle requête entrante.

Ceci peut être utile pour par exemple définir des variables dans les objets
req et res qui pourront être accessibles à tout le reste de l’application.

Il suffit simplement d’utiliser la fonction use() de l’objet app.

app.use(checkAuth)
app.use(“/user/:id”, checkAuth)
Requêtes avec données dans le corps
Requêtes avec données dans le corps
BodyParser

C’est une bibliothèque vous permettant de directement


parser le corps d’une requête. Le résultat sera directement
disponible dans l’objet request.

BodyParser est middleware.

$ npm install body-parser


BodyParser

const bodyParser = require("body-parser")

// Content-type: application/json
app.use(bodyParser.json())

// Content-type: application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
BodyParser

app.post("/products", (req, res) => {


product = {
name: req.body.name,
price: req.body.price
}
res.json(product)
})
MongoDB
MongoDB

C’est une base de données orientée documents.


Contrairement à une base de données relationnelle, une
BDOD garde un ensemble de collections (tables)
composées d’un ensemble de documents (lignes).

Un document n’est rien d’autre qu’un objet JSON. En réalité


cet objet JSON sera stocké en tant qu’objet BSON (Binaire).
{
_id: 5abe492a8cbadb22dc80ab54
"nom": "iPhone X",
"prix": 1159
}
MongoDB: Schéma

Contrairement à une base de données relationnelle le


schéma n’est pas fixé à l’avance.
Une même collection peut contenir différents documents
(objets) de structure différentes.
{
_id: 5abe492a8cbadb22dc80ab54
"nom": "iPhone X",
"prix": 1159
}
{
_id: 4afe3fe83611502135847759
"nom": "iPhone X",
"description": "Dernier iPhone"
}
MongoDB vs DB relationnelle

Une des plus grandes différences est que dans MongoDB il


n’y a pas de clés étrangères ou de jointures.

Cependant, il est possible à un document JSON d’inclure un


autre document JSON mais il ne peut pas le référencer.

Évidemment, il est toujours possible de référencer un autre


document à travers son _id, mais il faudra le faire
manuellement.

MongoDB est ce qu’on appelle une base de données


NoSQL.
MongoDB

Une fois mongoDB installé, il faudra le lancer depuis


le terminal:
$ mongod
Le serveur sera donc lancé et écoutera sur le port
27017.
Afin d'interagir avec le serveur, il est possible
d’utiliser le client mongo depuis le terminal:
$ mongo
Commandes shell MongoDB

> show dbs


Affiche toutes les bases de données.

> use NomBD


Passer de la BD courante à la BD NomBD.

> show collections


Affiche les collections de la BD courante.
MongoDB et NodeJS

Afin de pouvoir interagir avec la base de données


MongoDB depuis NodeJS, il nous faudra récupérer
un nouveau module qu’on appel driver.
Il existe plusieurs drivers mongoDB pour NodeJS,
nous allons dans cours utiliser le module officiel
“MongoDB”:
$ npm install mongodb --save
Objets du module MongoDB

Le module propose plusieurs objets permettant de


manipuler les bases de données, collections et
documents:
- L’objet db qui nous permet de récupérer les
collections d’une base de donnée précise.
- L’objet Collection permet de récupérer, insérer,
modifier et supprimer des documents.
- Les documents sont simplement des objets
JavaScript.
MongoDB: récupérer l’objet Db

Pour récupérer la référence de l’objet db, il faudra


utiliser la fonction suivante:
MongoClient.connect(url, callback)
Où:
- url: est la chaîne de caractère utilisée pour se
connecter à mongodb.
- callback: Fonction appelée une fois connecté
avec comme argument la référence à l’objet db.
MongoDB: récupérer l’objet Db

const MongoClient = require('mongodb').MongoClient;


const MONGO_URL = 'mongodb://localhost:27017/maDb';

// Avec callback
MongoClient.connect(MONGO_URL, (err, database) => {
db = database;
})
MongoDB: récupérer l’objet Db

const MongoClient = require('mongodb').MongoClient;


const MONGO_URL = 'mongodb://localhost:27017/maDb';

let db = null;
function onConnected(err, database) {
db = database;
}

// Avec promesse
MongoClient.connect(MONGO_URL)
.then(onConnected)
MongoDB: récupérer l’objet Collection

Une fois l’objet db récupéré, il est possible de récupérer


l’objet collection à travers une fonction que possède l’objet
db:

const coll = db.collection(“maCollection”)

La fonction collection est synchrone.

Elle nous retourne un objet que l’on peut utiliser pour


ajouter/rechercher/modifier/supprimer des documents dans
notre collection.

Si la collection n’existe pas, elle sera automatiquement créé


au moment de l'écriture.
collection.insertOne()

collection.insertOne(doc, callback);

Permet d’insérer un document dans une collection.


- doc: n’est rien d’autre qu’un objet Javascript
contenant les données qui seront sauvegardées
dans notre collection en tant que document.
- callback: fonction qui sera appelée à la fin de la
sauvegarde, elle a deux arguments: err, result. où
result.insertedId représente le _id du document.
collection.insertOne()

function insertProduct(name, price) {


const product = {
"name": name,
"price": price
}

collection.insertOne(product, (err, result) => {


console.log(result.insertedId)
})
}
collection.findOne()

collection.findOne(query [, options], callback);

Permet de rechercher un document ayant les caractéristiques


spécifiées dans la query.
La query n’est autre qu’un objet Javascript ayant les associations
clés/valeur que l’on recherche.
collection.findOne()

function findProduct(name) {
collection.findOne(
{"name": name},
(err, product) => {
return product;
}
)
}
collection.findOne() avec ObjectID

Et si on souhaitait retrouver un document à partir de son _id?


function findProduct(id) {
collection.findOne(
{"_id": id},
(err, product) => {
return product;
}
)
}
collection.findOne() avec ObjectID

Et si on souhaitait retrouver un document à partir de son _id?


function findProduct(id) {
collection.findOne(
{"_id": id},
(err, product) => { Ne marche pas !
return product;
}
)
}
collection.findOne() avec ObjectID

Avant de rechercher un document avec son _id, il nous faut


convertir la chaîne de caractère que l’on a qui correspond à
son _id en un ObjectID.
const ObjectID = require('mongodb').ObjectID

function findProduct(id) {
collection.findOne( {"_id": ObjectID(id)},
(err, product) => {
return product;
})
}
collection.find()

Fonctionne de la même manière que findOne() à


l’exception qu’elle nous retourne non pas un document mais
un curseur qui pointe sur le premier document.

On peut utiliser hasNext et next pour avancer le curseur.


Requêtes et projections
Curseur et .toArray()

Chaque curseur possède une fonction permettant de le


convertir en un tableau possédant tous les documents que le
curseur pointe dans les limites de la mémoire disponible.

collection.findOne(...).toArray((err, items) => {


return items;
})
collection.update()

collection.update(query, newDocument);

C’est la version la plus basique pour mettre à jour des


documents. Elle permet de directement remplacer les documents
qui correspondent à la query avec le contenu de newDocument.
collection.update()

function updateProduct(name, price) {


const old_product = {
"name": name
}
const new_product = {
"name": name,
"price": price
}

collection.update(old_product, new_product)
}
collection.update() et upsert

collection.update(query, newDocument, params);

En plus des arguments vus précédemment, la fonction update


supporte aussi d’autres paramètres en argument, tel l’argument
upsert qui permet à la fonction en plus de mettre à jour le
document, d’automatiquement créer l’entrée si la query ne
retourne aucun résultat.
collection.update() et upsert

function updateProduct(name, price) {


const old_product = {
"name": name
}
const new_product = {
"name": name,
"price": price
}
const params = { upsert: true}

collection.update(old_product, new_product, params)


}
collection.deleteOne()

collection.deleteOne(query, callback);

Permet de supprimer le premier document qui correspond à


la query.

Le callback reçoit en paramètre: err et result, ou result


possède une variable result.deletedCount qui indique le
nombre de document supprimés, dans ce cas-ci un seul.
collection.deleteMany()

collection.deleteMany(query, callback);
Permet de supprimer tous les document qui correspondent à
la query.

Le callback reçoit en paramètre: err et result, ou result


possède une variable result.deletedCount qui indique le
nombre de document supprimés, dans ce cas-ci un seul.

collection.deleteMany()
Permet de vider toute la collection en une fois.
Opérateurs de Requêtes sur les documents

MongoDB possède une syntaxe particulière pour les


requêtes permettant de faire des recherches plus
sophistiquées.
Optimisation: indexes

// On crée notre index

db.records.createIndex( { userid: 1 } )

// On crée notre index multiple de produits

db.products.createIndex( { item: 1, category: 1,

price: 1 } )

// Query executée très rapidement

db.records.find( { userid: { $gt: 10 } } )


Optimisation: connexions multiples (pooling)

const MongoClient = require('mongodb').MongoClient;


const MONGO_URL = 'mongodb://localhost:27017/maDb';

let db = null;
function onConnected(err, database) {
db = database;
}

// Avec promesse
MongoClient.connect(MONGO_URL, {poolSize: 10})
.then(onConnected)
MongoDB: réplication
Utiliser MongoDB avec ExpressJS

MongoClient.connect(MONGO_URL, (err, database) => {


db = database;
app.get(“/”, (req, res) => {
db.collection(“products”).find({}, (err, items)
=> { res.json(items) })
})
app.listen(3000, () => {
console.log("En attente de requêtes...")
})
})
Utiliser MongoDB avec ExpressJS

let db = null;
function onConnected(err, database) {
db = database;
app.get(“/”, (req, res) => {
db.collection(“products”).find({}, (err, items)
=> { res.json(items) })
})
}

MongoClient.connect(MONGO_URL)
.then(onConnected)
MongoDB: Studio 3T
Authentification
Types d’authentification: Basic Auth
Types d’authentification: Basic Auth

L’authentification peut se faire deux manières différentes:

- Directement dans l’URL:

http://toto:[email protected]

- En tant que header:

Authorization: Basic AZIBAFJRFjpPcGVuU84JFN1l


Types d’authentification: API Key

La clé peut être transmise dans l’URL ou l’en-tête.


Types d’authentification: JSON Web Token

C’est un standard définissant une méthode légère et


sécurisée pour transmettre une information à travers un objet
JSON.

L’information étant transmise, on pourra aisément vérifier sa


validité.

header.payload.signature
JWT: Header

Le header contient généralement deux informations:

- Le type du token, dans notre cas JWT.


- L’agorithme de hashage utilisé, tels HMAC SHA256 ou
RSA.

{
"alg": "HS256",
"typ": "JWT"
}

Par la suite, il sera encodé en Base64Url.


JWT: Payload

Il est composé de 3 types de “réclamations” (claims):

1. réclamations inscrites: Non obligatoire, représente des


informations utiles: iss (issuer), exp (expiration time), sub
(subject), aud (audience), ...
2. réclamations publiques: Libre, définies par le
développeur.
3. réclamations privées: réclamations spécifiques qui ne
sont ni des réclamations inscrites ou publiques.
JWT: Payload

Voici un exemple:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}

Par la suite, il sera encodé en Base64Url.


JWT: Signature

La signature est utilisée pour s’assurer que les informations


n’ont pas été modifiées en chemin.

Il est également possible si on utilise un algorithme


asymétrique de s’assurer à travers elle que la personne qui a
transmis l’information est bien celle qu'elle dit qu’elle est.

HMACSHA256(base64UrlEncode(header) + "." +
base64UrlEncode(payload), secret)
OAuth1a, OAuth2

OAuth (protocol d’autorisation) permet a une application


d’avoir une autorisation pour accéder à certaines
informations.

Vous aimerez peut-être aussi