How Can I Pass a Parameter to a setTimeout() Callback in JavaScript

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.

Related blog posts