Utilisation de this dans la fonction setInterval dans une classe

cs_le cafard Messages postés 10 Date d'inscription jeudi 15 février 2007 Statut Membre Dernière intervention 18 mars 2010 - 16 févr. 2007 à 16:49
PetoleTeam Messages postés 3426 Date d'inscription lundi 26 décembre 2005 Statut Membre Dernière intervention 14 janvier 2011 - 23 févr. 2007 à 05:16
Bonjour,

Je rencontre un problème avec l'utilisation de this dans la fonction setInterval dans une classe.
Je reprends mon exemple (cf. http://www.javascriptfr.com/infomsg_DIAPORAMA-JAVASCRIPT_860013.aspx#6 ) :

function Diaporama(iInterval)
{
 this.iInterval = iInterval;
 this.oTimer = "";

 this.changeImage = function()
 {
    ...
  }

 this.startDiaporama = function()
 {
  var oThis = this;
  this.oTimer = window.setInterval(oThis.changeImage(), this.iInterval); 
 }

}

L'interpréteur Javascript tombe en erreur sur la commande setInterval après avoir exécuté 1 fois la commande << oThis.changeImage()
>>

J'ai essayé également ceci mais sans plus de succès :
window.setInterval(oThis.changeImage(), 1000); 

10 réponses

PetoleTeam Messages postés 3426 Date d'inscription lundi 26 décembre 2005 Statut Membre Dernière intervention 14 janvier 2011 17
16 févr. 2007 à 17:42
B
onjour...

Ton problème n'est donc pas tout à fait le même 1000 excuses...
...d'une manière générale je pense qu'il est préférable de procéder comme suit.

//-- Création d'une fonction dans la zone globale
function Get_Fct_Change( o_){
  return( function(){o_.changeImage()});
// return l'adresse de la fonction
}

ensuite on fait l'appel de la façon suivante
  this.oTimer = setTimeout( Get_Fct_Show(this), this.iInterval);

Voila ça fonctionne nickel pour moi alors...
pour info je prépare une  source pour cela, tu en as la primeur...

Nota :
Le principe est expliqué à l'adresse suivante
http://developer.mozilla.org/fr/docs/Le_principe_de_fermeture_en_JavaScript:Utilisation_des_fermetures

;0)
0
cs_le cafard Messages postés 10 Date d'inscription jeudi 15 février 2007 Statut Membre Dernière intervention 18 mars 2010
17 févr. 2007 à 12:00
Merci PetoleTeam. Mais ça ne marche pas chez moi.

En lisant le lien, j'ai modifié comme suit :
    this.startDiaporama = function()
    {
        var iInterval = this.iInterval;
        var refChangeImage = this.changeImage();

        this.oTimer = window.setInterval( "refChangeImage;", iInterval);
    }

J'ai aussi essayé :
        this.oTimer = window.setInterval( refChangeImage, iInterval);

        this.oTimer = setTimeout( "refChangeImage;", iInterval);


        this.oTimer = setTimeout( "efChangeImage, iInterval);


Comme au début, j'ai la 1ère image qui s'affiche, mais la suite ne défile pas.

Quand le lien dit "l’argument this ne correspond pas à l’objet lui-même", c'est bien ce que je comprends.
0
PetoleTeam Messages postés 3426 Date d'inscription lundi 26 décembre 2005 Statut Membre Dernière intervention 14 janvier 2011 17
19 févr. 2007 à 17:47
B
onjour...
je suis surpris que l'exemple que je t'ai fourni ne fonctionne pas mais bon...peut être à cause du setTimeout au lieu du setInterval.

Rappel :
 setTimeout doit être réappellé, opération ponctuelle retardée, alors de setInterval instancie un timer qui relance la fonction et ce donc sans rappel.

Dans ton cas si tu lances le diaporama avec startDiaporama il te faut éfféctivement un setInterval, sinon avec le setTimeout il te faudrait le mettre dans la fonction changeImage.

Le probléme vient que tu déclares une variable en local, car avec var devant, alors qu'il la faut global pour qu'elle existe encore quand la fonction en cours ce termine.
Lorsque la fonction liée au setTimeout ou au setInterval ce déclenche après delai, la variable n'existe plus.

Donc plusieures solutions et entre autre

this.startDiaporama = function(){
  
oThis = this; // variable global sans le var devant
  //-- Avec les guillemets c'est une expression qui sera évaluée, pas de ; en fin
  this.oTimer = window.setInterval("oThis.changeImage()", this.iInterval); 
  //-- Sans les guillemets c'est un pointeur sur fonction
  this.oTimer = window.setInterval( oThis. changeImage, this.iInterval); 
}
je reste persuadé que l'application de
  this.oTimer = setInterval( Get_Fct_Show(this), this.iInterval);
doit fonctionner...

Tiens nous au courant...
;0)
0
cs_le cafard Messages postés 10 Date d'inscription jeudi 15 février 2007 Statut Membre Dernière intervention 18 mars 2010
20 févr. 2007 à 22:34
Voici les résultats :

  //-- Avec les guillemets c'est une expression qui sera évaluée, pas de ; en fin
  this.oTimer = window.setInterval(" oThis. changeImage()", this.iInterval);
  //--> Marche

  //-- Sans les guillemets, avec les parentheses, pas de ; en fin
  this.oTimer = window.setInterval(oThis.changeImage(), this.iInterval);
  //--> Marche

  //-- Sans les guillemets, sans les parentheses, sans le ;
  this.oTimer = window.setInterval( oThis. changeImage, this.iInterval); 

  //--> Ne marche pas

Pour l'utilisation d'une fonction intermédiaire :
  this.oTimer = setInterval( Get_Fct_Show(this), this.iInterval);

  //--> Ne marche pas

Utilisation de setTimeout 
à la place de setInterval 
dans startDiaporama
et ajout de cette commande setTimeout   dans
changeImage
: ne marche pas.

Voila toutes les réponses aux tests demandés. J'ai donc gardé la 1ère solution mais j'ai un problème si j'ai 2 diaporamas sur la même page. Le problème vient de l'utilisation de oThis en variable globale.
Dans ma page HTML, j'ai 2 images. Pour chacune de ces images j'ai 2 instances de classes : diapo1 et diapo2.

Le 1er diaporama se déclanche dès que je pointe ma souris sur la 1ère image et que je sors de la zone de cette image.
Mais lorsque je fais la même chose sur la 2nde image, le 2ème diaporama se lance et le 1ère s'arrête.
Aussi sur le 2ème diaporama les intervalles de temps déclarés pour diapo1 et  diapo2 se chevauchent.
Lorsque je reviens sur le 1er, celui-ci reprends la relève et le 2nd s'arrête.

Donc l'utilisation d'une variable global oThis ne résoud pas mon affaire de classe.

Merci tout de même PetoleTeam pour le suivi de tes réponses. Chapeau !
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
PetoleTeam Messages postés 3426 Date d'inscription lundi 26 décembre 2005 Statut Membre Dernière intervention 14 janvier 2011 17
20 févr. 2007 à 23:12
B
onjour...bonsoir plutôt quand c'est plus tard..

premier constat
 - tu bosses avec IE, car il ne supporte pas le passage sans les guillemets

second constat
 - c'est tout la limite de l'objet en variable globale, si plusieurs appel à la fonction sont faite il change de valeur entre chaque est cela devient vite la pagaille si les appels ne sont pas parfaitement alternés

troisième constat
 - c'est la raison de la solution avec la Get_Fct_Show(this) qui bien que sans guillement fonctionne sous IE et qui ne marche d'ailleur pas avec, ??? why IE ???

Le problème est peut être ailleurs
as tu une adresse ou l'on peut voir, ou le code si il n'y a pas 3513 lignes.

;0)
0
cs_le cafard Messages postés 10 Date d'inscription jeudi 15 février 2007 Statut Membre Dernière intervention 18 mars 2010
21 févr. 2007 à 10:35
Je travaille sous Mozilla Firefox et parfois sous IE. Mais c'est vrai que les tests ci-dessus avaient été effectués sous Firefox et non sous IE.
L'exemple en ligne, je te le prépare dans la journée car pour l'instant je travaille en local.

J'ai trouvé une solution pas très jolie mais qui fonctionne : j'utilise la redondance.
Je m'explique :

1) Fichier Javascript :
// Constructeur
function Diaporama(sName, sHtmlImgName, iInterval)
{
    // Propriétés
    this.sName = sName; // Nom de l'instance de classe Diaporama
    // (...)

    this.startDiaporama = function()
    {
        this.timerID = window.setInterval( this.sName + ".changeImage()", this.iInterval); //marche
    }

}

2) Fichier HTML
<!-- (...) -->
<script language ="javascript">
var diapo1 = new Diaporama( "diapo1" , "IMG_Diaporama1", 1000);
var diapo2 = new Diaporama("diapo2", "IMG_Diaporama2", 3000);
</script>
<!-- (...) -->


<!-- (...) -->


<!-- (...) -->
0
PetoleTeam Messages postés 3426 Date d'inscription lundi 26 décembre 2005 Statut Membre Dernière intervention 14 janvier 2011 17
21 févr. 2007 à 17:36
B
onjour...
solution pas très jolie mais qui fonctionne, est utilisée fréquement, c'est l'ESSENTIEL...

une autre solution du même type est de déclarer un compteur global que l'on incrément en entrant dans la constructeur, puis que l'on utilise pour initialise this.Obj

exemple :
var Diapo_Count= 0;
//----------------------
function Diaporama(.....){
  Diapo_Count ++;
  this.Obj = "Obj"+ Diapo_Count;
  eval( this.Obj +"=this");
  ....
  this.Start = function() {
    this.timerID = window.setInterval( this.Obj + ".changeImage()", this.iInterval);    }
}

cela revient en fait au même si ce n'est un paramètre de moins...

mais ce qui me turlupine quand même c'est que la soluce avec Get_Fct_Show(this) ne fonctionne pas pour toi

?0)
0
cs_le cafard Messages postés 10 Date d'inscription jeudi 15 février 2007 Statut Membre Dernière intervention 18 mars 2010
23 févr. 2007 à 00:02
Merci PetoleTeam de cette solution plus jolie que la mienne. Au moins ça m'évite de rappeler mon instance de classe en paramètre de type chaîne. C'est plus propre d'éviter la redondance.
Ca ne résout pas le problème de l'utilisation de This dans setInterval ou set TimeOut mais ta dernière solution me suffit pour aboutir à mon but de réaliser une classe Diaporama.
Tout est dans la commande eval
que je n'ai pas encore bien maîtrisé. A lire quelques sites, cette commande est nouvelle et n'est très connue.

A propos de la solution Get_Fct_Show(this) j
e t'envoie l'adresse de ma page par MP.

Encore merci pour tes solutions proposées.
0
cs_le cafard Messages postés 10 Date d'inscription jeudi 15 février 2007 Statut Membre Dernière intervention 18 mars 2010
23 févr. 2007 à 00:16
Salut PetoleTeam,

En fait c'est en t'écrivant mon MP, que j'ai compris d'où venait l'erreur à propos de  Get_Fct_Show(this)
.
J'ai fait un copier/coller bêtement :

//-- Création d'une fonction dans la zone globale
function Get_Fct_Change( o_){
  return( function(){o_.changeImage()});
// return l'adresse de la fonction
}

ensuite on fait l'appel de la façon suivante
  this.oTimer = setTimeout( Get_Fct_Show(this), this.iInterval);

Je t'envoie tout de même le lien au cas où tu as besoin de faire un test.
0
PetoleTeam Messages postés 3426 Date d'inscription lundi 26 décembre 2005 Statut Membre Dernière intervention 14 janvier 2011 17
23 févr. 2007 à 05:16
B
onjour...
HOU LA le vrai BO
U
L
ET

on m'a pourtant toujours prévenu que quand on est dans une logique d'erreur il faut arrêter puis reprendre depuis le début.
1000 excuses pour cette faute de frappe aliant ton contexte et le mien.
on va pouvoir passer à autre chose...
Bonne continuation...
;0)
0
Rejoignez-nous