Archives de catégorie : Javascript

Les hooks React (2/3)

Hier on a parlé du state, dont on peut maintenant bénéficier dans les composant « fonction ». Peut-être cela n’a-t-il pas suffi à vous convaincre : après tout le gain n’est pas évident si vous êtes passé à Redux par exemple, le state, c’est un peu de l’histoire ancienne (on en reparlera dans le prochain article ;)). Abordons alors maintenant le cycle de vie des composants.

Continuer la lecture

« this », c’est qui ? C’est quoi ?

Note : cet article a été originellement publié (par moi-même) sur le site du ByteClub le 25 octobre 2017.

S’il y a bien un mot-clé en JavaScript qui fait frémir les plus chevronnés des développeurs (sans faire sourciller les débutants, encore insouciants), c’est this. Cette espèce de variable magique dont on croit pouvoir maîtriser la valeur mais qui n’en fait qu’à sa tête, qui est-il ? D’où vient-il ? Formidable robot des temps nouveaux

Faisons un tour rapide 🙂

Continuer la lecture

Les hooks React (1/3)

Avant-propos : des nouvelles de ce blog

Ça faisait des années que j’avais laissé ce blog pour mort, il est temps de le sortir de sa torpeur !

Je contribuais principalement sur byteclub.fr mais cet épisode étant terminé et comme on a lamentablement laissé mourir le domaine et le site, je vais rapatrier ici les articles. Et continuer à en produire ici-même 🙂 à commencer par une série de 3 articles pour faire le tour des hooks React, et la traduction d’un article complet sur le server-side rendering.

Dans le vif du sujet : alors c’est quoi ces hooks ?

Les hooks (lire l’introduction officielle) sont une des grosses nouveautés de React, une de celle qui a généré une ébulition dans la communauté comme rarement. Et pour cause : elle permet d’accéder dans les composants « fonction » à des fonctionnalités jusqu’ici réservées aux classes.

Continuer la lecture

Écrire des scripts npm multi-plateforme

npm c’est très bien, j’ai complètement abandonné gulp, grunt, et consors, et je commence même à embrasser ma condition d’allergique au fichier de conf (le package.json sera mon unique tolérance). Bref, si comme moi votre « task runner » est npm, alors comme moi vous avez du vous heurter au cas des « autres » plateformes, celles qui n’ont pas les mêmes commandes que vous, voire pas de commande du tout pour ce que vous voulez faire… c’est-à-dire Windows et son shell de Néandertal. Voici donc une série de modules node qui résolvent ces questions. Continuer la lecture

Mes 2 patterns autour des promises

TL;DR: Les promesses c’est meilleur avec du sucre fonctionnel.

En réaction à l’article « My five promise patterns », j’avais envie de partager ma façon de faire. En effet si je le rejoins sur une grande partie, je trouve qu’il a oublié d’insister sur des points bien plus essentiels…

Choisir sa librairie, mais rester proche du natif

À part Q (dernier sur tous les benchmarks, sauf quand il y a aussi jQuery) il n’y a pas vraiment de mauvais choix. Personnellement j’utilise souvent Bluebird qui représente pour moi le meilleur rapport fonctionnalités/performances (voire performances tout court). Ceci étant dit, j’ai lancé son benchmark sur ma propre machine et j’ai trouvé des résultats bien différents de ce que l’auteur avance 😉 Je pense donc de plus en plus utiliser when.js.

Moralité : les promesses étant une partie fondamentale (flow control) de votre programme, il ne faut pas se laisser enfermer dans une librairie qui vous priverait de gains de performances significatifs. Donc au final je préfère éviter au maximum d’utiliser les fonctionnalités supplémentaires genre Promise#map() & co.

Continuer la lecture

Ma boite à outil Node.js

Voilà le genre d’article qui peut servir à tout le monde, et qui peut devenir une formidable opportunité d’échange pour moi si vous venez partager vos propres « batbelt » en commentaire. Donc n’hésitez pas 🙂

Je travaille au quotidien avec Node.js (à tel point que j’ai presque oublié comment ça marchait côté client ;)), et vous imaginez donc que j’ai des millions d’outils super bien gaulés pour me faciliter la vie au quotidien. Raté ! Il y en a finalement assez peu, et ce sont les grands classiques que vous connaissez déjà probablement. Mais qui sait, si ce n’est pas le cas, ce post pourrait changer un petit bout de votre vie !

Séance bookmarks, c’est parti.

Continuer la lecture

Les promesses en JavaScript

Yet another article about promises… Oui, exactement 🙂

Pourquoi cet article ?

Parce que je n’ai jamais trouvé que les promesses pouvaient m’apporter quoi que ce soit, qu’async faisait très bien le job et tous les comparatifs qu’on a pu me montrer ne m’ont jamais convaincu.

Néanmons je sentais bien, vu le nombre de mecs beaucoup plus intelligents que moi qui en étaient convaincus, que c’était « mieux ». Mais de là à m’en convaincre… Supposant ne pas être le seul mécréant pour les mêmes raisons, et récemment convaincu, je me devais donc de partager les raisons qui ont fini de me convaincre.

TL;DR : Les promesses ne sont pas (que) du flow control, les réduire à ça les dessert immanquablement face à async & consors. L’isolation des traitements et la gestion d’erreur sont bien plus décisifs.

Continuer la lecture

L’agrégation sur un serveur MongoDB mono-instance : NON

J’ai eu récemment de gros problèmes de performances sur un serveur, lié à MongoDB. Je vais donc vous présenter le problème et sa solution 🙂

TL;DR : Tout le code est ici pour faire le test vous-même.

Le contexte général : on a une collection assez large de documents comportant un code de regroupement et une valeur numérique. On cherche à faire une agrégation très classique consistant à prendre l’item dont la valeur numérique est la plus haute, regroupé par le code de regroupement.

Par exemple : on a une collection d’articles (auteur, date, texte) et on veut sortir la liste des derniers articles postés par auteur. Pour l’exemple j’ai préparé une collection de 50’000 documents à valeurs aléatoires (auteur parmi une liste pré-définie, date dans les 3 derniers mois).

Si on connaît bien MongoDB, on va utiliser le framework d’agrégation. Mais dans mon cas avec un MongoDB 2.2, impossible.

La map/reduce

Du coup, on se rabat logiquement sur un map/reduce :

// Article grouped by author
function map () {
  emit(this.author, this);
}
 
// Keep max date
function reduce (key, articles) {
  return articles.sort(function (a1, a2) { return a2.date - a1.date })[0]
}
 
…
.then(mapReduce(map, reduce))

C’est lent. Sur ma machine avec un mongodb en 2.4 ça tourne à ~900 ms. Sur le serveur dont je parlais au début, en 2.2, ça tape dans les 5 secondes (ouch).

Le map/reduce avec béquille

J’ai donc essayé de simplifier le map/reduce, me disant que « sort » devait être trop coûteux. Je sors donc juste la date max par auteur, puis je fais un find :

// Date grouped by author
function map () {
  emit(this.author, this.date);
}
 
// Keep max date
function reduce (key, dates) {
  return Math.max.apply(null, dates)
}
 
…
.then(mapReduce(map, reduce))
// Build query: big $or
.then(function (results) {
  return {$or: results.map(function (result) {
    return {author: result._id, date: new Date(result.value)}
  })})
.then(find)

On y gagne, mais ça reste lent. Sur ma machine concrètement on passe de ~900 ms à ~700 ms, c’est quand-même un beau gain de plus de 20%.

On abandonne le map/reduce

Du coup j’ai essayé la méthode débile. J’ai sorti la liste des clés possibles (la liste des auteurs ici), puis pour chacun fait une requête avec un tri sur la date. Dans notre exemple ça donnerait quelque-chose comme ça :

…
.then(find({}, {author: 1}) // [{author: "Bob"}, {author: "John"}]
.then(pluck('author'))      // ["Bob", "John"]
.then(function (authors) {
  // N queries in concurrency
  return Q.all(authors.map(function (author) {
    // max date's article for this author
    return find({author: author}).sort({date: -1}).limit(1).nextObject()
  }))
})

Le résultat est sans appel : le premier « find » prend en moyenne ~270 ms, les N « find » suivant au total ~60 ms pour un total de ~330 ms soit un gain supérieur à 60%. Et comme c’est la première requête qui prend l’essentiel du temps, si on a la possibilité d’avoir la liste des auteurs de manière moins coûteuse (par exemple une valeur en configuration, ou simplement les listes d’une collection tierce, ce qui dans notre exemple aurait été plus logique) on peut vite diviser par 10 le temps de réponse initial.

Ce fut mon cas, je suis passé de 5 secondes à 0.5 secondes sur mon serveur, en passant de 1 à N+1 requête (une quinzaine dans ce cas).

Conclusion

Comparaison des méthodes

Pour l’anecdote, le problème ne s’était pas posé sur notre premier serveur de recette monté un peu à l’arrache et surtout… branché sur un server mongodb dans le cloud (Clever Cloud en l’occurrence). Et dans ce cas le map/reduce fonctionnait très bien.

Tout ça pour dire : N’oubliez donc pas que MongoDB est mono-threadé, en plus d’avoir un runtime plutôt lent, et que donc s’il n’est pas capable de distribuer les calculs… il vaut mieux ne pas lui en demander 🙂 N’oubliez pas de jeter un œil au TL;DR : code des tests.