Il y a 8 ans -
Temps de lecture 5 minutes
Transformez votre code Node.js grâce au module de promises Bluebird
Lorsqu’on parle de promises dans l’écosystème Node.js, on pense immédiatement à la librairie Q. Toutefois, il existe de nombreux modules de promises proposant chacun des choses différentes. En particulier, le module bluebird se démarque grâce à des fonctionnalités tout à fait intéressantes telles que la “promisification”.
Promisification
Les core modules de Node.js fonctionnent à base de callback. Ainsi pour lire un fichier de façon asynchrone, il faut appeler la fonction readFile du module fs et traiter la réponse depuis le callback passé en dernier paramètre de la fonction lors de son appel :
if err
console.error "unable to read file"
try
val = JSON.parse(val);
console.log val.success
catch e
console.error "invalid json in file"[/javascript]
Bluebird permet de transformer le code précédent dans le code suivant :
console.log val.success
.catch SyntaxError, (e) ->
console.error "invalid json in file"
.catch (e) ->
console.error "unable to read file"[/javascript]
promisifyAll
Cette transformation est rendue possible grâce à la promisification du module fs, via l’appel de la fonction promisifyAll qui permet de transformer toutes les fonctions exposées en fonctions renvoyant des promises :
Promise.promisifyAll fs
fs.readFileAsync("file.js", "utf8").then(…)[/javascript]
Selon toute vraisemblance, les fonctions du modules sont proxifiées via un wrapping changeant la signature.
On pourra noter que le chaînage de fonctions catch sur la promise permet de différencier le traitement des erreurs en fonction de leur type. Ici, l’erreur de type SyntaxError est traitée différemment des erreurs typées autrement.
promisify
Il est également possible de ne promisifier qu’une seule fonction grâce à la fonction promisify :
redisGet(‘foo’).then () ->
#…[/javascript]
Il y a tout de même un piège puisque la fonction attend 2 paramètres. Le premier étant la référence de la fonction à promisifier, et le second étant l’objet auquel la fonction est rattachée.
nodeify
La fonction nodeify est également très intéressante car elle permet d’enregistrer un callback sur une promise bluebird et d’appeler celui-ci à la résolution de cette dernière :
[javascript gutter= »true »]getDataFor(input, callback) ->
dataFromDataBase(input).nodeify(callback)
[/javascript]
Cette possibilité est particulièrement intéressante, car elle permet de construire des API qui deviennent utilisables aussi bien par du code qui fonctionne à base de callback, qu’avec du code à base de promise.
Ainsi, si le callback est renseigné, il sera appelé. Sinon, il suffira d’exploiter la promise retournée par la fonction pour obtenir et traiter le résultat de l’appel.
Exemple exploitant le mécanisme de promise :
console.log dataForMe[/javascript]
Le même exemple exploitant le mécanisme de callback:
if err
console.error err
console.log dataForMe[/javascript]
spread
En temps normal, le code suivant donnera en résultat la tableau : [1, 2, 3].
[javascript gutter= »true »]Promise.resolve([1,2,3]).nodeify (err, result) ->
# err == null
# result: [1,2,3]
[/javascript]
Toutefois, l’option {spread: true} passée à l’appel de la fonction nodeify, permet de dispatcher les valeurs de résultat sur l’ensemble des arguments de la fonction de callback renseignée:
# err == null
# a == 1
# b == 2
# c == 3
, {spread: true}[/javascript]
Last but not least, la performance
Les librairies de promesses ont souvent été décriées pour le piètre performances. L’auteur de Bluebird s’est attaché à fournir une librairie performante aussi bien au niveau de l’usage du CPU que de la mémoire. Il décrit dans un article sur Github différents extraits de code tueurs de performance:
Les chiffres parlent plus qu’une longue explication :
Ceux-ci datent du mois de mai 2014. Il peuvent donc ne plus être complètement à jour, mais permettent de se faire une idée des performances obtenues avec Bluebird et de les comparer à d’autres librairies de promesses ou bien encore d’autres techniques asynchrones.
[bash] ├── async@0.7.0
├── davy@0.2.2
├── deferred@0.7.1
├── kew@0.4.0
├── lie@2.7.3
├── promise@5.0.0
├── q@1.0.1
├── rsvp@3.0.6
├── vow@0.4.3
└── when@3.1.0
bench doxbee-sequential
results for 10000 parallel executions, 1 ms per I/O op
file time(ms) memory(MB)
promises-bluebird-generator.js 171 16.52
callbacks-baseline.js 197 20.68
promises-bluebird.js 280 26.64
promises-lvivski-davy.js 616 58.75
promises-dfilatov-vow.js 672 80.59
promises-cujojs-when.js 731 68.74
callbacks-caolan-async-waterfall.js 733 44.57
promises-calvinmetcalf-lie.js 1035 113.07
promises-obvious-kew.js 1047 78.50
promises-tildeio-rsvp.js 1121 109.49
promises-ecmascript6-native.js 1298 96.05
promises-then-promise.js 1775 134.73
promises-medikoo-deferred.js 2238 149.61
promises-kriskowal-q.js 19786 415.04
Platform info:
Windows_NT 6.1.7601 ia32
Node.JS 0.11.13
V8 3.25.30
Intel(R) Core(TM) i5-2500K CPU @ 3.30GHz × 4
bench parallel (`–p 25`)
results for 10000 parallel executions, 1 ms per I/O op
file time(ms) memory(MB)
promises-bluebird.js 483 63.32
callbacks-baseline.js 545 25.54
promises-bluebird-generator.js 574 64.66
promises-lvivski-davy.js 1088 128.62
promises-cujojs-when.js 1527 178.57
callbacks-caolan-async-parallel.js 1635 99.87
promises-dfilatov-vow.js 1753 196.96
promises-then-promise.js 2553 338.36
promises-ecmascript6-native.js 3749 309.55
promises-obvious-kew.js 3805 366.32
promises-tildeio-rsvp.js 3916 462.23
promises-calvinmetcalf-lie.js 4477 230.99
promises-medikoo-deferred.js 4613 356.03
Platform info:
Windows_NT 6.1.7601 ia32
Node.JS 0.11.13
V8 3.25.30
Intel(R) Core(TM) i5-2500K CPU @ 3.30GHz × 4[/bash]
Le lien : https://github.com/petkaantonov/bluebird/blob/master/benchmark/stats/latest.md
Conclusion
La librairie bluebird est riche en fonctions pour le moins intéressantes, vous pouvez les retrouver sur la page de documentation du projet GitHub :
Lien : https://github.com/petkaantonov/bluebird/blob/master/API.md
Si vous n’utilisez pas les promesses ou n’êtes pas encore tout à fait convaincu de leur intérêt, vous pouvez en lire plus au sujet des promesses dans l’article suivant : http://spion.github.io/posts/why-i-am-switching-to-promises.html
Commentaire
0 réponses pour " Transformez votre code Node.js grâce au module de promises Bluebird "
Published by Luc , Il y a 7 ans
Bon article, je cherchais justement de la doc sur ce module. Thanks !