L’enfer des callbacks
date post
15-Apr-2017Category
Engineering
view
314download
0
Embed Size (px)
Transcript of L’enfer des callbacks
Lenfer des callbacksUn cas dtude en *(Node)JS
Aurlien Bourdon@aurelienbourdon
describe('.totalValue', function() {
it('should calculate the total value of items in a space', function(done) {
var table = new Item('table', 'dining room', '07/23/2014', '1', '3000');
var chair = new Item('chair', 'living room', '07/23/2014', '3', '300');
var couch = new Item('couch', 'living room', '07/23/2014', '2', '1100');
var chair2 = new Item('chair', 'living room', '07/23/2014', '4', '500');
var bed = new Item('bed', 'dining room', '07/23/2014', '1', '2000');
table.save(function() {
chair.save(function() {
couch.save(function() {
chair2.save(function() {
bed.save(function() {
Item.totalValue({room: 'dining room'}, function(totalValue) {
expect(totalValue).to.equal(5000); done();
});
});
});
});
});
});
});
});Sources
http://thecodebarbarian.com/2015/03/20/callback-hell-is-a-mythhttps://atdreamstate.wordpress.com/2014/12/26/hell-hellfire/
Pourquoi est-ce lenfer ?
Pourquoi est-ce lenfer ?
Lecture en cascade
Pourquoi est-ce lenfer ?
Lecture en cascade
Absence de description fonctionnelle
Pourquoi est-ce lenfer ?
Lecture en cascade
Couplage fort entre les fonctions
Absence de description fonctionnelle
Pourquoi est-ce lenfer ?
Lecture en cascade
Lisibilit hardue
Maintenance difficile
Sourcehttp://memesvault.com/sad-meme-face/
Absence de description fonctionnelle
Couplage fort entre les fonctions
Cas dtude
function parseCurrentDir() {
fs.readdir('.', function (err, files) {
if (err) {
console.error(err);
} else {
files.forEach(function (file) {
fs.readFile(file, 'utf8', function (err, content) {
if (err) {
console.error(err);
} else {
console.log(content);
}
});
});
}
});
}
#1 Modularisation
Modularisation ?
Nommage et externalisation des fonctions
function parseCurrentDir() {
fs.readdir('.', function (err, files) {
if (err) {
console.error(err);
} else {
files.forEach(function (file) {
fs.readFile(file, 'utf8', function (err, content) {
if (err) {
console.error(err);
} else {
console.log(content);
}
});
});
}
});
}
function parseCurrentDir() {
fs.readdir('.', function readFiles(err, files) {
if (err) {
console.error(err);
} else {
files.forEach(function readFile(file) {
fs.readFile(file, 'utf8', function printContent(err, content) {
if (err) {
console.error(err);
} else {
console.log(content);
}
});
});
}
});
}
function readFile(file) {
fs.readFile(file, 'utf8', printContent);
}
function printContent(err, content) {
if (err) {
console.error(err);
} else {
console.log(content);
}
}
function parseCurrentDir() {
fs.readdir('.', readFiles);
}
function readFiles(err, files) {
if (err) {
console.error(err);
} else {
files.forEach(readFile);
}
}
function readFile(file) {
fs.readFile(file, 'utf8', printContent);
}
function printContent(err, content) {
if (err) {
console.error(err);
} else {
console.log(content);
}
}
function parseCurrentDir() {
fs.readdir('.', readFiles);
}
function readFiles(err, files) {
if (err) {
console.error(err);
} else {
files.forEach(readFile);
}
}
#2 Dcouplage
Dcouplage ?
Sparation des traitements du flow dexcution
Dcouplage ?
Sparation des traitements du flow dexcution
En utilisant des promises :-)
Promises ?
Abstraction servant de proxy pour un rsultat non-connu au moment o il est rfrenc pour la
premire fois, car son calcul ou son obtention se feront plus tard lexcution
- Wikipdia
Promises !
(...)
(...)
Promises !
https://github.com/kriskowal/q
function parseCurrentDir() {
fs.readdir('.', readFiles);
}
function parseCurrentDir() {
fs.readdir('.', function (err, files) {
});
}
function parseCurrentDir() {
fs.readdir('.', function (err, files) {
});
}
function parseCurrentDir() {
Q.Promise(function (resolve, reject, notify) {
fs.readdir('.', function (err, files) {
});
});
}
function parseCurrentDir() {
Q.Promise(function (resolve, reject, notify) {
fs.readdir('.', function (err, files) {
if (err) {
reject(err);
} else {
resolve(files);
}
});
});
}
function parseCurrentDir() {
return Q.Promise(function (resolve, reject, notify) {
fs.readdir('.', function (err, files) {
if (err) {
reject(err);
} else {
resolve(files);
}
});
});
}
function parseCurrentDir() {
return Q.Promise(function (resolve, reject, notify) {
fs.readdir('.', function (err, files) {
if (err) {
reject(err);
} else {
resolve(files);
}
});
});
}
Sparation des traitements du flow dexcution
readFiles(files);
function listCurrentDirFiles() {
return Q.Promise(function (resolve, reject, notify) {
fs.readdir('.', function (err, files) {
if (err) {
reject(err);
} else {
resolve(files);
}
});
});
}
Sparation des traitements du flow dexcution
readFiles(files);
Mais comment lier notre fonction avec la suivante ?
Mais comment lier notre fonction avec la suivante ?
En utilisant le chanage de promises !
listCurrentDirFiles()
listCurrentDirFiles()
.then(readFiles)
listCurrentDirFiles()
.then(readFiles)
.then(...)
listCurrentDirFiles()
.then(readFiles)
.then(...)
.catch(console.error)
listCurrentDirFiles()
.then(readFiles)
.then(...)
.catch(console.error)
.done()
Du coup au final a donne quoi ?
function parseCurrentDir() {
fs.readdir('.', function (err, files) {
if (err) {
console.error(err);
} else {
files.forEach(function (file) {
fs.readFile(file, 'utf8', function (err, content) {
if (err) {
console.error(err);
} else {
console.log(content);
}
});
});
}
});
}
function parseCurrentDir() {
listCurrentDirFiles()
.then(readFiles)
.then(printContents)
.catch(console.error)
.done();
}
function readFile(file) {
return Q.Promise(function (resolve, reject) {
fs.readFile(file, 'utf8', function (err, content) {
if (err) {
reject(err);
} else {
resolve(content);
}
});
});
}
function printContents(contents) {
contents.forEach(function (content) {
if (content.state === 'fulfilled') {
console.log(content.value);
} else {
console.log('Unable to parse file due to %s', content.reason);
}
});
}
function listCurrentDirFiles() {
return Q.Promise(function (resolve, reject) {
fs.readdir('.', function (err, files) {
if (err) {
reject(err);
} else {
resolve(files);