When working with JavaScript timers, developers often use the setTimeout() function to delay the execution of code. However, many beginners encounter a common issue when trying to pass parameters to a function inside setTimeout().
For example, consider the following JavaScript code:
function statechangedPostQuestion()
{
//alert("statechangedPostQuestion");
if (xmlhttp.readyState==4)
{
var topicId = xmlhttp.responseText;
setTimeout("postinsql(topicId)",4000);
}
}function postinsql(topicId)
{
//alert(topicId);
}
When running this code, an error occurs:
ReferenceError: topicId is not defined
In this article, we will explain why this error occurs, how setTimeout() works, and the correct ways to pass parameters to a callback function.
Understanding the setTimeout() Function
The setTimeout() function in JavaScript is used to execute a function after a specified delay (in milliseconds).
Syntax
setTimeout(function, delay);
Parameters:
- function – The function to execute.
- delay – Time in milliseconds before execution.
Simple Example
setTimeout(function(){
console.log("Hello after 2 seconds");
},2000);
Output after 2 seconds:
Hello after 2 seconds
Why the Error Happen
In the problematic code:
setTimeout("postinsql(topicId)",4000);
The function is passed as a string instead of a real function.
When JavaScript receives a string inside setTimeout(), it treats it similar to eval() and executes it in the global scope.
However, the variable topicId was declared inside the function:
var topicId = xmlhttp.responseText;
So when the timeout executes later, topicId is no longer available, resulting in:
ReferenceError: topicId is not defined
(Recommended): Use an Anonymous Function
The best practice is to pass a function instead of a string.
Correct Code
function statechangedPostQuestion()
{
if (xmlhttp.readyState == 4)
{
var topicId = xmlhttp.responseText; setTimeout(function(){
postinsql(topicId);
},4000);
}
}function postinsql(topicId)
{
console.log("Topic ID:", topicId);
}
Why This Works
The anonymous function remembers the variable topicId using a concept called a closure. When the timeout executes, the value is still available.
Using Arrow Functions (Modern JavaScript)
If you are using ES6 JavaScript, you can write cleaner code using arrow functions.
function statechangedPostQuestion()
{
if (xmlhttp.readyState == 4)
{
let topicId = xmlhttp.responseText; setTimeout(() => postinsql(topicId), 4000);
}
}function postinsql(topicId)
{
console.log("Topic ID:", topicId);
}
This method is shorter and widely used in modern JavaScript.
Passing Parameters Directly
Modern browsers allow passing parameters directly after the delay.
setTimeout(postinsql, 4000, topicId);
Example
function statechangedPostQuestion()
{
if (xmlhttp.readyState == 4)
{
var topicId = xmlhttp.responseText;
setTimeout(postinsql, 4000, topicId);
}
}function postinsql(topicId)
{
console.log("Topic ID:", topicId);
}
Complete Working Example
Below is a complete example simulating an AJAX response and delayed function execution.
// Simulated xmlhttp object
var xmlhttp = {
readyState: 4,
responseText: "12345"
};function statechangedPostQuestion()
{
if (xmlhttp.readyState == 4)
{
var topicId = xmlhttp.responseText; console.log("Request finished. Topic ID:", topicId); setTimeout(function(){
postinsql(topicId);
},4000);
}
}function postinsql(topicId)
{
console.log("Data sent to SQL with Topic ID:", topicId);
}// Run function
statechangedPostQuestion();
Output
Request finished. Topic ID: 12345
(wait 4 seconds)
Data sent to SQL with Topic ID: 12345
Common Mistakes to Avoid
Using String Execution
setTimeout("postinsql(topicId)",4000);
Problems:
- Poor performance
- Scope issues
- Security risks
- Harder debugging
Forgetting Scope
Variables defined inside a function are not available globally.
Conclusion
Passing parameters to a setTimeout() callback is simple once you understand how JavaScript handles function scope.
The main mistake developers make is passing a string instead of a function, which causes variables like topicId to become undefined.
The best approach is to use:
setTimeout(() => postinsql(topicId), 4000);
This method keeps your code clean, safe, and compatible with modern JavaScript practices.
