1. 6th of June, 2015
Asynchronous Javascript
Common and useful patterns
by Steven Rémot
2. 6th of June, 2015
Table of contents
1. Callbacks
2. Promises
3. Generators
3. 6th of June, 2015
Table of contents
1. Callbacks
2. Promises
3. Generators
4. 6th of June, 2015
Callbacks - Usage
function GameController() {
var dirChangedCb = function () {};
this.onDirectionChanged = function (callback) {
dirChangedCb = callback;
};
document.addEventListener('keydown', function (event) {
dirChangedCb(determineEventDirection(event));
});
}
var gc = new GameController();
gc.onDirectionChanged(function (direction) {
hero.move(direction);
});
5. 6th of June, 2015
Callbacks - Avoiding conflicts
function GameController() {
var dirChangedCb = function () {};
this.onDirectionChanged = function (callback) {
dirChangedCb = callback;
};
document.addEventListener('keydown', function (event) {
dirChangedCb(determineEventDirection(event));
});
}
var gc = new GameController();
gc.onDirectionChanged(function (direction) {
hero.move(direction);
});
gc.onDirectionChanged(function (direction) {
enemy.reactTo(direction);
});
Only one callback is saved
6. 6th of June, 2015
Callbacks - Avoiding conflicts
function GameController() {
var dirChangedCbs = [];
this.onDirectionChanged = function (callback) {
dirChangedCbs.push(callback);
};
document.addEventListener('keydown', function (event) {
for (var i = 0; i < dirChangedCbs.length; i++) {
dirChangedCbs[i](determineEventDirection(event));
}
});
}
var gc = new GameController();
gc.onDirectionChanged(function (direction) {
hero.move(direction);
});
gc.onDirectionChanged(function (direction) {
enemy.reactTo(direction);
});
7. 6th of June, 2015
Callbacks - Nested operations
function loadHero(loadingFinishedCallback) {
http.get('/characters/hero.json', function (heroData) {
loadingFinishedCallback({ data: heroData });
});
}
8. 6th of June, 2015
Callbacks - Nested operations
function loadHero(loadingFinishedCallback) {
http.get('/characters/hero.json', function (heroData) {
http.get(heroData.modelUrl, function (model) {
loadingFinishedCallback({
data: heroData,
model: model
});
});
});
}
9. 6th of June, 2015
Callbacks - Nested operations
function loadHero(loadingFinishedCallback) {
http.get('/characters/hero.json', function (heroData) {
http.get(heroData.modelUrl, function (model) {
http.get(model.materialUrl, function (material) {
loadingFinishedCallback({
data: heroData,
model: model,
material: material
});
});
});
});
}
10. 6th of June, 2015
Callbacks - Nested operations
function loadHero(loadingFinishedCallback) {
http.get('/characters/hero.json', function (heroData) {
loadGraphics(heroData.modelUrl, function (graphics) {
loadingFinishedCallback({
data: heroData,
model: graphics.model,
material: graphics.material
});
});
});
}
11. 6th of June, 2015
Callbacks - Limits
● Nested callbacks are not handy
● Even worse with error catching
● Waiting for multiple callbacks is hard
Callbacks are bad for async operations
12. 6th of June, 2015
Table of contents
1. Callbacks
2. Promises
3. Generators
13. 6th of June, 2015
Promises - Basics
function httpGet(url) {
return new Promise(function (resolve) {
http.get(url, function (data) {
resolve(data);
});
});
}
14. 6th of June, 2015
Promises - Basics
function httpGet(url) {
return new Promise(function (resolve) {
http.get(url, resolve);
});
}
15. 6th of June, 2015
Promises - Basics
function httpGet(url) {
return new Promise(function (resolve, reject) {
http.get(url, resolve, reject);
});
}
21. 6th of June, 2015
Promises - Waiting all promises
function loadObjects() {
return Promise.all([
loadHero(),
loadEnemy(),
loadDoor(),
loadWall(),
// ...
]);
}
loadObjects().then(function (objects) {
var hero = objects[0];
var enemy = objects[1];
// ...
});
22. 6th of June, 2015
Promises - How to get them
● In Ecmascript 6 standard library
● Available through polyfills:
https://github.com/jakearchibald/es6-promise
● Alternative APIs:
https://github.com/kriskowal/q
https://github.com/petkaantonov/bluebird
23. 6th of June, 2015
Promises
Nice, but…
● Verbose
● Still writing in an asynchronous way
We can do better!
24. 6th of June, 2015
Table of contents
1. Callbacks
2. Promises
3. Generators
25. 6th of June, 2015
Generator - Basics
function* counter() {
for (var i = 0; i < 10; i++) {
yield i;
}
}
var count = counter();
console.log(count.next()); // 0
console.log(count.next()); // 1
// ...
29. 6th of June, 2015
Generator - Browser support
● Generator are ES6
● Async functions are ES7
● Use them today with transpilers:
https://github.com/google/traceur-compiler
https://babeljs.io/
30. 6th of June, 2015
Thanks for listening!
References:
https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Promise
https://www.promisejs.org/
https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Instructions/function*
https://github.com/lukehoban/ecmascript-asyncawait
31. 6th of June, 2015
Join the community !
(in Paris)
Social networks :
● Follow us on Twitter : https://twitter.com/steamlearn
● Like us on Facebook : https://www.facebook.com/steamlearn
SteamLearn is an Inovia initiative : inovia.fr
You wish to be in the audience ? Join the meetup group!
http://www.meetup.com/Steam-Learn/