views:

2182

answers:

3

I have some JavaScript code that looks like:

function statechangedPostQuestion()
{
  //alert("statechangedPostQuestion");
  if (xmlhttp.readyState==4)
  {
    var topicId = xmlhttp.responseText;
    setTimeout("postinsql(topicId)",4000);
  }
}

function postinsql(topicId)
{
  //alert(topicId);
}

I get a error that topicId is not defined Everything was working before i used the setTimeout() function.

I want my postinsql(topicId) function to be called after some time. What should i do?

+11  A: 
setTimeout(function() {
    postinsql(topicId);
}, 4000)

You need to feed an anonymous function as a parameter instead of a string, the latter method shouldn't even work per the ECMAScript specification but browsers are just lenient. This is the proper solution, don't ever rely on passing a string as a 'function' when using setTimeout() or setInterval(), it's slower because it has to be evaluated and it just isn't right.

meder
I remember I took me some time to get to this conclusion. Sometimes inside objects I think, the regular book call with '' doesn't work. I still dont know exactly why,,, but this was my solution aswell
Elzo Valugi
`window.setTimeout` is a DOM method, and as such is not defined by the ECMAScript specification. Passing a string has always worked in browsers, and is a _de facto_ standard—in fact, ability to pass a function object was added later, with JavaScript 1.2—it is explicitly part of the HTML5 draft spec (http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#get-the-timed-task). However, using a string instead of a function object is generally considered poor style because it is essentially a form of delayed `eval()`.
Miles
Eck - my memory isn't serving me right today.. setTimeout isn't defined by ES yes, but I don't think it's an *official* DOM method that you'll find in the spec, just a DOM 0 method ( supported in browsers since the early days ).
meder
It's not in the W3C DOM specification, correct. So? Your assertion that "the latter method shouldn't even work per the ECMAScript specification but browsers are just lenient" is still wrong.
Miles
Yes, as indicated by the "setTimeout isn't defined by ES" in my prior comment my first one was incorrect.
meder
I see a lot of answers to this question out there in the wild using the "Just quote it as a string". While it seems like people are saying that should work, I often run into the 'not defined' error via that method while the anonymous function option always works.
DA
A: 

Replace

 setTimeout("postinsql(topicId)",4000);

with

 setTimeout("postinsql(" + topicId + ")",4000);

EDIT:

Brownstone's comment is incorrect, this will work as intended, as demonstrated by running this in the Firebug console

(function() {
  function postinsql(id) {
    console.log(id);
  }
  var topicId = 3
  window.setTimeout("postinsql(" + topicId + ")",4000); // outputs 3 after 4 seconds
})();

Note that I'm in agreeance with others that you should avoid passing a string to setTimeout as this will call eval() on the string and instead pass a function.

Russ Cam
This will not work because the *result* of postinsql(topicId) will be executed by setTimeout. You need to wrap it in a function as with the first answer, or use a helper like Prototype's .curry() -- setTimeout(postinsql.curry(topidId),4000);
brownstone
@brownstone: That's incorrect. The string will be evaluated when the timeout fires.
Miles
A: 

I think you want:

setTimeout("postinsql(" + topicId + ")", 4000);
+1 - Some people are a bit over zealous with the down voting - even with working solutions like this one.
Sean Bright
I've run into instances where that simply does not work (always resulting in a 'function not defined' error) but using the anonymous function does work. Which is frustrating given that everyone seems to say the above syntax should always work. (could it be that jQuery somehow gets in the way of the 'quote as string' method?)
DA