2008-10-26 5 views
12

J'essaie d'appeler un setTimeout à partir d'un rappel setInterval:Comment résoudre Var hors de portée dans les appels setTimeout

function callback() 
{ 
    //assign myVar 
    var myVar = document.getElementById("givenID"); 
    //... 
    //now wait 2 secs then call some code that uses myVAr 
    setTimeout("myVar.innerHTML = 'TEST'", 2000); 
} 

setInterval("callback();", 10000); 

setInterval fonctionne comme prévu, mais l'appel setTimeout échoue. Je suppose que le problème est lié au fait que je référence une variable (myVar) qui n'est pas dans la portée.

Quelle est la meilleure façon de résoudre ce problème?

+0

utilisant des fermetures comme je l'ai indiqué ci-dessous fonctionnerait autour de cela, la fermeture intérieure a accès à la portée de la fermeture extérieure. – FlySwat

+0

Il me manque quelque chose - essayez-vous d'économiser de la performance en précalculant myVar? Pourquoi pas setTimeout ("document.getElementById (" givenID "). InnerHTML = 'TEST'", 2000); ? –

+1

N'utilisez pas de guillemets avec setTimout/setInterval, cela force l'exécution de JS à appeler Eval, qui exécute le code dans un nouveau contexte, d'où le problème de portée. – FlySwat

Répondre

32

C'est un candidat idéal pour la fermeture:

setInterval(
    function() 
    { 
     var myVar = document.getElementById("givenID"); 
     setTimeout(
      function() 
      { 
       // myVar is available because the inner closure 
       // gets the outer closures scope 
       myVar.innerHTML = "Junk"; 
      },2000); 
    }, 10000); 

Votre problème est portée lié, et cela fonctionnerait autour de cela.

+0

Je suppose que vous avez raison - j'ai édité la question – JohnIdol

+2

Ainsi illustrant une excellente raison de ne pas passer des chaînes comme paramètres à setTimeout et setInterval! :-) –

+0

bien sûr Andrew - je vous ai voté :-) – JohnIdol

1

Exécutez-le dans Firefox et cochez Outils | Console d'erreur. Si setTimeout échoue, il peut vous indiquer pourquoi.

En outre, essayez de remplacer "someFunction();" par "alert('hi')" (sans point-virgule) et de voir si cela fonctionne. Si c'est le cas, le problème est considérablement réduit.

+0

acclamations - J'ai fait cela et j'ai remarqué que le problème n'était pas lié à setTimeout - voir edit – JohnIdol

4

En plus pratique, essayez de ne pas utiliser des chaînes comme paramètres pour setTimeout et setInterval parce que invoqueront eval ... En utilisant le formulaire ci-dessous pourrait également ce problème plus facile à comprendre/debug:

setInterval(function() { 
    // do stuff 
    // ... 
    // now wait 2 secs then call someFunction 
    setTimeout(someFunction, 2000); 
}, 10000); 
+0

bonne suggestion - merci – JohnIdol

11

J'ai eu un problème similaire. Le problème était que j'essayais d'appeler une méthode de l'intérieur à l'aide d'un setTimeout(). Quelque chose comme ça, QUI NE FONCTIONNE PAS POUR MOI:

function myObject() { 

    this.egoist = function() { 
     setTimeout('this.egoist()', 200); 
    } 

} 

myObject001 = new myObject(); 
myObject001.egoist(); 

Ce qui suit n'a pas non plus FONCTIONNE:

... setTimeout(egoist, 200); 
... setTimeout(egoist(), 200); 
... setTimeout(this.egoist, 200); 
... setTimeout(this.egoist(), 200); 
... setTimeout(function() { this.egoist() }, 200); 

La solution a consisté à utiliser() déclaration comme ceci:

function myObject() { 

    this.egoist = function() { 
     with (this) { setTimeout(function() { egoist() }, 200);} 
    } 

} 

myObject001 = new myObject(); 
myObject001.egoist(); 

Bien sûr, c'est un cycle sans fin, mais le point que je fais ici est différent.

Hope this helps :)

+0

nice, le 'avec' déclaration est sous-évalué à mon avis .. – Alex

+0

cela a aidé: D merci –

+2

découvrir "avec (ceci) "a fait ma journée, merci! – WebChemist