Utilisation de setInterval() dans une Class

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Utilisation de setInterval() dans une Class

par naholyr » 21 oct. 2006, 10:15

Ah oui au fait note que la dernière release de prototype.js n'offre pas de méthode "stop()" à PeriodicalExecuter. Pour en bénéficier, deux solutions :

1. Utiliser la 1.5.0_RC1 de prototype.js

2. Appliquer un "patch" en exécutant ce code (tiré de la 1.5.0) après inclusion de la librairie :
PeriodicalExecuter.prototype.registerCallback = function() {
  this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
}
PeriodicalExecuter.prototype.stop = function() {
  if (!this.timer) return;
  clearInterval(this.timer);
  this.timer = null;
}

par Ajoloca » 20 oct. 2006, 22:34

Bonsoir,

Merci naholyr, bien des choses que je connais pas. Je vais prendre du temps pour bien étudier tout ça.

Encore merci pour tes explications claires.

par naholyr » 20 oct. 2006, 21:52

Le problème c'est que "this.display()" ca n'existe pas dans le corps d'exécution de setInterval().
Une méthode simple (et la plus propre que j'ai trouvée) est de globaliser l'objet, et de faire appeler la variable gloable par setInterval(). Je m'explique (dans tous les cas d'implémentation qui vont suivre, l'utilisation est var obj=new MaClass(); obj.start();) :
function MaClasse() {

  // initialisation de mon objet
  this.compteur = 1;

  this.start = function() {
    setInterval("this.incremente()", 1000);
  }

  this.incremente = function() {
    this.compteur++;
    alert(this.compteur);
  }

}
Ceci ne va bien sur pas fonctionner.
L'idée, c'est d'ajouter une variable globale qui vaut tout simplement "this" :
function MaClasse() {

  // initialisation de mon objet
  this.compteur = 1;

  // creation d'un nom global
  this.nomGlobal = "objetGlobal";

  // globalisation de l'objet
  window[this.nomGlobal] = this;

  this.start = function() {
    setInterval("window." + this.nomGlobal + ".incremente()", 1000);
  }

  this.incremente = function() {
    this.compteur++;
    alert(this.compteur);
  }

}
Et voilà ça marche :) (note que pour un code maxi-portable, on pourrait aussi bien utiliser MaClasse en lieu et place de window, on crée alors des attributs de classe à la volée au lieu de créer des variables globales)
Afin d'éviter les effets de bord lorsque plusieurs objets sont instanciés, on va créer un nouveau nom global unique a chaque création d'objet :
var prefixeGlobal = "__objet__";
var uniqid = 0;
do {
  this.nomGlobal = prefixeGlobale + (uniqid++);
} while (typeof window[this.nomGlobal] != "undefined");
Voici donc la méthode que j'utilise quand je le fais "from scratch".

Le plus propre restant d'utiliser une librairie tres bien fichue, j'ai nommé prototype.js, voici comment on réecrirait tout ca, sans user de l'horrible "globalisation", grâce à l'incommensurablement maginifiquement bien pensé "bind()" (et pourtant si simple, il suffisait d'y penser et de bien connaître la mecanique interne de Javascript bien sûr) :
function MaClasse() {

  // initialisation de mon objet
  this.compteur = 1;

  this.start = function() {
    setInterval(this.incremente.bind(this), 1000);
  }

  this.incremente = function() {
    this.compteur++;
    alert(this.compteur);
  }

}
Et voici comment on l'écrirait en "esprit prototype.js"
var MaClasse = Class.create();
MaClasse.prototype = {
  initialize : function() {
    this.compteur = 1;
  },
  start : function() {
    this.timer = new PeriodicalExecuter(this.incremente.bind(this), 1);
  },
  incremente : function() {
    this.compteur ++;
    alert(this.compteur);
  }
});

par Ajoloca » 20 oct. 2006, 20:41

Re,

Il-y-a une solution mais elle ne me semble pas très propre (dans l'idée POO) car là j'apelle une fonction "horpheline" à l'objet qui de plus peut être appelée sans avoir construit l'objet

Au lieu de déclarer la fonction dans la class elle-même, la déclarer à l'extérieur.

Code : Tout sélectionner

this.start = demarre; }// END-class function demarre() { // Démarrage du compteur this.tempo = setInterval('this.display', 1000); }// END-start

par Cyrano » 20 oct. 2006, 20:29

Effectivement, je viens de tester rapidement en local : la POO en JavaScript et moi, ça fait malheureusement encore deux. Le problème ne vient pas des quotes mais de la structure dans l'imbrication des fonctions, je maîtrise pas assez pour t'aider efficacement là-dessus :?

par Ajoloca » 20 oct. 2006, 20:16

Bonjour Cyrano,

J'avais bien essayé cette solution, mais comme je dis dans le post, j'ai des erreurs JS

Avec le code en l'état
Erreur : useless setInterval call (missing quotes around argument?)
Fichier source : http://www.joloca.eu/~jose/Compteur.class.js
Ligne : 32
Avec les quotes
Erreur : this.display is not a function
Fichier source : http://www.joloca.eu/~jose/Compteur.class.js
Ligne : 32

par Cyrano » 20 oct. 2006, 20:08

Oui, il manque des quotes pour encadrer le nom de la fonction appelée par setInterval. Essaye comme ceci :
function Compteur(param1, ...)
{
   this.tempo = null;
   this.temps = param;
   this.display = function()
   { // Fonction d'affichage
      if(this.temps <= 0)
      {
         clearInerval(this.tempo);
         return(false);
      }
      alert('Dans section de traitement');
      // Affichage des zones
      // Décompte
   } // END-display
   this.start = function()
   { // Démarrage du compteur
      this.tempo = setInterval('this.display()', 1000);
   }// END-start
}// END-class 

Utilisation de setInterval() dans une Class

par Ajoloca » 20 oct. 2006, 20:02

Bonjour,

Je cherche à utiliser la fonction setInterval() dans une class et je n'y arrive pas.
Mon code:

Code : Tout sélectionner

function Compteur(param1, ...){ this.tempo = null; this.temps = param; this.display = function(){ // Fonction d'affichage if(this.temps <= 0){ clearInerval(this.tempo); return(false); } alert('Dans section de traitement'); // Affichage des zones // Décompte } // END-display this.start = function(){ // Démarrage du compteur this.tempo = setInterval(this.display(), 1000); }// END-start }// END-class
que je voudrais appeller de la façon suivante :

Code : Tout sélectionner

var myObj = new Compteur(param1, ...); myObj.start();
Avec cette syntaxe j'ai le message d'erreur 'Il manque des quotes', si je les mets 'La fonction this.display() n'existe pas'.

J'ai le PB avec les 3 navigateurs dans lesquels j'ai testé (FF/Linux, Opéra/Linux, IE/WinXP)

Une idée ?
Merci d'avance pour votre aide.