syn : ensemble
Exemples : synthèse, synopsis, synchrétisme
chronos : le temps
Exemples : chronologie, chronomètre
Qui ne se fait pas en même temps.
log("Maintenant");
setTimeout(function() {
log("Plus tard");
}, 2000);
log("Maintenant aussi");
var xhr = new XMLHttpRequest();
log("Maintenant");
xhr.addEventListener("load", function() {
log("Plus tard : " + xhr.responseText);
});
xhr.open("GET", "/data/greeting.txt", true);
xhr.send(null);
log("Maintenant aussi");
Code du serveur répondant à la requête précédente :
var fs = require('fs'), http = require('http');
http.createServer(function (req, res) {
fs.readFile(__dirname + req.url, function (err, data) {
res.writeHead(200);
setTimeout(function() { // Délai artificiel pour la démo
res.end(data);
}, 2000);
});
}).listen(8080);
L'exécution du code asynchrone est déclenchée par des événements.
Exemples :
Algorithme très simplifié :
// Pseudo code
while (true) { // Boucle sans fin
// Recherche les événements actifs
activeEvents = pollForActiveEvents(eventQueue);
activeEvents.forEach(function(activeEvent) {
// Exécute les fonctions associées
activeEvent.callback();
eventQueue.remove(activeEvent);
});
}
log("D'abord");
setTimeout(function() {
log("Finalement");
}, 0);
log("Ensuite");
log("D'abord");
setTimeout(function() {
log("Finalement");
}, 0);
log("Ensuite");
function request(url, callback) {
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", function() {
callback(xhr.responseText);
});
xhr.open("GET", url, true);
xhr.send(null);
}
log("Envoi de la requête");
request("/data/greeting.txt", function(data) {
log("Réponse reçue : " + data);
});
request("/data/data1.json", function(data) {
log(data);
var value1 = JSON.parse(data).value;
request("/data/data2.json", function(data) {
log(data);
var value2 = JSON.parse(data).value;
request("/data/data3.json", function(data) {
log(data);
var value3 = JSON.parse(data).value;
log("Résultat : " + (value1 + value2 + value3));
});
});
});
request("/data/data1.json", function(data) {
var value1 = JSON.parse(data).value;
getData2(value1);
});
function getData2(value1) {
request("/data/data2.json", function(data) {
var value2 = JSON.parse(data).value;
getData3(value1, value2);
});
}
function getData3(value1, value2) {
request("/data/data3.json", function(data) {
var value3 = JSON.parse(data).value;
log("Résultat : " + (value1 + value2 + value3));
});
}
C'est une opération
function requestPromise(url) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", function() {
resolve(xhr.responseText);
});
xhr.open("GET", url, true);
xhr.send(null);
});
}
var value1, value2, value3;
requestPromise("/data/data1.json").then(function(data) {
log(data); value1 = JSON.parse(data).value;
return requestPromise("/data/data2.json");
}).then(function(data) {
log(data); value2 = JSON.parse(data).value;
return requestPromise("/data/data3.json");
}).then(function(data) {
log(data); value3 = JSON.parse(data).value;
log("Résultat : " + (value1 + value2 + value3));
});
var value1, value2, value3;
requestPromise("/data/data1.json").then(function(data) {
log(data); value1 = JSON.parse(data).value;
return requestPromise("/data/invalid.json");
}).then(function(data) {
log(data); value2 = JSON.parse(data).value;
return requestPromise("/data/data3.json");
}).then(function(data) {
log(data); value3 = JSON.parse(data).value;
log("Résultat : " + (value1 + value2 + value3));
}).catch(function(err) {
log(err);
});
Promise.all([
requestPromise("/data/data1.json"),
requestPromise("/data/data2.json"),
requestPromise("/data/data3.json")
]).then(function(responses) {
var values = responses.map(
(text) => JSON.parse(text).value
);
log("Résultat : " + sum(values));
});
var cache = new Map(), url = "/data/data1.json";
function getWithCache(url) {
if (cache.has(url)) {
return Promise.resolve(cache.get(url)); // Promesse déjà résolue
} else {
var promise = requestPromise(url)
promise.then(function(value) { // 1er then
cache.set(url, value);
});
return promise;
}
}
getWithCache(url).then(function(value) { // 2ème then
log(value);
getWithCache(url).then(log);
});
fetch("/data/data1.json")
.then((response) => response.json())
.then((data) => log(data.value));
Promise.all([
fetch("/data/data1.json"),
fetch("/data/data2.json"),
fetch("/data/data3.json")
]).then(function(responses) {
Promise.all(
responses.map(response => response.json())
).then(function(data) {
var values = data.map((obj) => obj.value);
log("Résultat : " + sum(values));
});
});
function *mygen() {
yield "Bonjour";
var name = yield "Comment t'appelles-tu ?";
yield "Enchanté " + name + " !";
}
var it = mygen();
var yieldedValue = it.next(); // {"value":"Bonjour","done":false}
log(JSON.stringify(yieldedValue));
function *mygen() {
yield "Bonjour";
var name = yield "Comment t'appelles-tu ?";
yield "Enchanté " + name + " !";
}
var it = mygen();
log(it.next().value);
log(it.next().value);
log(it.next("Toto").value); // Passage de valeur au générateur
log(JSON.stringify(it.next()));
Deux significations :
function *main() {
var response = yield requestWrapper("/data/greeting.txt");
log(response);
}
function requestWrapper(url) {
return request(url, function(data) {
it.next(data);
});
}
var it = main();
it.next();
function *main() {
var response = yield requestPromise("/data/greeting.txt");
log("Réponse : " + response);
}
var it = main();
var promise = it.next().value;
promise.then(function(response) {
it.next(response);
});
Fonction run issue de You don't know JS: Async & Performance
run(function *main() {
var response = yield fetch("/data/greeting.txt");
var text = yield response.text();
log(text);
var responses = yield Promise.all([
fetch("/data/data1.json"),
fetch("/data/data2.json"),
fetch("/data/data3.json")
]);
var data = yield Promise.all(
responses.map((response) => response.json())
);
var numbers = data.map((item) => item.value);
log(sum(numbers));
});
async function main() {
var response = await fetch("/data/greeting.txt");
var text = await response.text();
log(text);
var responses = await Promise.all([
fetch("/data/data1.json"),
fetch("/data/data2.json"),
fetch("/data/data3.json")
]);
var data = await Promise.all(
responses.map((response) => response.json())
);
var numbers = data.map((item) => item.value);
log(sum(numbers));
}
main();
L'évènementiel à son paroxisme
Tout devient un flux observable auquel on peut s'inscrire :
variables, propriétés, structures de données, ...
Des outils de manipulation de flux déjà connus :
merge, filter, map
Chaque évènement peut transmettre :
une valeur, une erreur, ou un signal de fin de flux
On s'inscrit alors au flux afin de réagir lors d'un évènement.
Les fonctions définis sont les observers alors que le flux lui est l'observable
function requestObservable(url) {
return Rx.Observable.create((observer) => {
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", () => {
observer.onNext(xhr.responseText);
observer.onCompleted();
});
xhr.open("GET", url, true);
xhr.send(null);
});
}
var res = 0;
var ob1 = requestObservable("/data/data1.json");
var ob2 = requestObservable("/data/data2.json");
var ob3 = requestObservable("/data/data3.json");
var merged = Rx.Observable.merge(ob1, ob2, ob3);
merged.subscribe(
v => {
var value = JSON.parse(v).value;
log(value);
res += value
},
e => log("Error: " + e),
() => log("Résultats : " + res)
);
var service = Rx.Observable.create(observer => {
var counter = 0;
setInterval(() => {
observer.onNext(counter++);
if (counter === 3) observer.onCompleted(42);
}, 1000);
return;
});
var component = service.subscribe(
function (x) {log('onNext: ' + x)},
function (e) {log('onError: ' + e)},
function () {log('onCompleted')}
);
MDN: Concurrency model and Event Loop
You Don't Know JS: Async & Performance
Table of contents | t |
---|---|
Exposé | ESC |
Autoscale | e |
Full screen slides | f |
Presenter view | p |
Source files | s |
Slide numbers | n |
Blank screen | b |
Notes | 2 |
Help | h |