Bonsoir,

J'aimerais réaliser un module de "Like / unlike", et donc cela sous entend une requête a chaque clique sur le bouton like (surtout si l'user s'amuse a cliquer 50 fois sur le bouton) pour modifier le statue en BDD. Et je pense qu'il y a quand même mieux en terme d'optimisation.

Alors dans le cas d'un seul post c'est vrai que ce n'est pas dérangeant. Mais dans le cas où il y a une bonne vingtaine de poste avec pas mal d'utilisateur qui clique simultanément sur des boutons Like / unlike ça risque de chauffer.

Donc j'aimerais savoir ce que vous me conseillerez.

6 réponses


Maenhyr
Réponse acceptée

Bonsoir,

Pour gérer le fait qu'un utilisateur clique 50 fois à la suite, tu peux implémenter un systême de bounce, c'est à dire que lorsque tu cliques, tu as un timer qui se décrémente. Lorsqu'il est à 0, tu lances ton appel. Chaque clic relance le timer.

Pour le fait de gérer plusieurs personnes qui likent en même temps, tu peux créer une queue, Chaque like va se mettre dans une queue et au bout d'un moment, tu va tous les gérer en même temps.

Lartak
Réponse acceptée

Bonsoir.
Tu pourrais par exemple limiter l'utilisateur à 1 like/dislike pour chaque post.
De cette manière il n'aura aucune raison de vouloir s'amuser à flooder le bouton de like s'il n'en a pas la possibilité de le faire.

Maenhyr
Réponse acceptée

Voila une implémentation de debounce et comment l'appeler

function debounce(fn, delay) {
  var timer = null;
  return function () {
    var context = this, args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function () {
      fn.apply(context, args);
    }, delay);
  };
}

$('.myButton').on('click', function() {
  debounce(function foobar() {
    // lancer la requete AJAX
    // ...
    // ...
  }, 300); // la fonction foobar se lancera 300ms apres le dernier clic de l'utilisateur
});

Pour la queue, tu peux regarder du côté de ton framework backend, il y a de grandes chances que cela soit déjà implémenté.

Maenhyr
Réponse acceptée
/**
  * Permet de lancer une fonction apres un certain delai
  * Si l'event appelant debounce est appelé avant le délai, le timer se réinitialise
  * @param fn la fonction à appeler
  * @param delay le délai en ms avant d'appeler fn
  */
function debounce(fn, delay) {
  // on crée une variable contenant notre timer
  // cette variable est crée à la création de la fonction debounce (donc une seule fois)
  var timer = null;

  // cette fonction myFn est appellée à chaque fois que debounce est appelé
  return function myFn() {
   // on récupère le contexte (this, car il change suivant le scope) et les arguments.
   // this : https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/this
   // arguments: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments
    var context = this, args = arguments;

    // on vide le timer actuel
    // cette fonction ne fait rien la premiere fois car timer est null
    // cette fonction stoppe le timer précédent lors des autres appels
    clearTimeout(timer);

    // on redéfinit un nouveau timer
    // on lui passe la fonction à appeler et le délai apres lequel la fonction sera appelée
    // https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout
    timer = setTimeout(function () {

      // on appele la fonction fn passée en paramètre en lui spécifiant le bon contexte et les arguments
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
      fn.apply(context, args);
    }, delay);
  };
}

// ATTENTION : j'utilise jQuery pour l'exemple
// on définit un listener sur l'event click pour un élément possédant la classe myButton
// lorsque cette élément est cliqué, on appelle la fonction clickButton.
$('.myButton').on('click', function clickButton() {

  // comme vu plus haut, ceci va appelé la fonction myFn contenue dans debounce
  debounce(function foobar() {
    // lancer la requete AJAX
    // ...
    // ...
  }, 300); // la fonction foobar se lancera 300ms apres le dernier clic de l'utilisateur
});

Pour l'array, c'est une version très simplifiée d'une queue mais tu peux le faire comme ça oui.

Laznet
Auteur

Donc pour en revenir au système de timer, si j'ai bien compris, si il clique 50 fois sur le bouton ça reset ce qui ne lancera pas la requête.
Et la queue pourrait être une sorte d'array ? et que quand il y a X "like" dans l'array je lance une requête ?

Dernière question : Comment mettrais tu en places le timer ? j'ai pensé a enregistrer l'heure a laquelle le bouton a été cliqué et a chaque clique j'actualise cette variable pour comparer avec un temps défini.

Laznet
Auteur

J'aimerais faire ça sans framework, car ce n'est pas pour un projet particulier mais juste pour le fun. Qu'en penses-tu donc de ma première idée ? (Celle est l'array).

Et tu peux un peu expliquer ton code, j'aimerais ne pas juste faire un simple copier coller, et au moins comprendre ce que j'écris.