911

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 an 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?

Donald Duck
  • 6,488
  • 18
  • 59
  • 79
Zeeshan Rang
  • 17,525
  • 27
  • 65
  • 96
  • 84
    it hurts a bit commenting on such an old topic but I just have to offer a third version (which in my opinion is much cleaner): setTimeout(postinsql.bind(null, topicId), 4000) – Hobblin Sep 13 '11 at 01:11
  • 3
    all is clear here: http://www.w3schools.com/jsref/met_win_settimeout.asp – Vladislav Oct 14 '15 at 11:43

28 Answers28

1198
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.

UPDATE:

As Hobblin said in his comments to the question, now you can pass arguments to the function inside setTimeout using Function.prototype.bind().

Example:

setTimeout(postinsql.bind(null, topicId), 4000);
ashleedawg
  • 17,207
  • 5
  • 53
  • 80
meder omuraliev
  • 171,706
  • 64
  • 370
  • 423
  • 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 Jul 27 '09 at 21:19
  • 30
    `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 Jul 27 '09 at 21:41
  • 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 omuraliev Jul 27 '09 at 21:56
  • 1
    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 Jul 27 '09 at 22:19
  • Yes, as indicated by the "setTimeout isn't defined by ES" in my prior comment my first one was incorrect. – meder omuraliev Jul 27 '09 at 23:36
  • 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. Apr 29 '10 at 17:57
  • Can someone tell me how you would clearTimeout on this example? – Neil Feb 21 '12 at 12:17
  • 2
    var temp = setTimeout(function() { postinsql(topicId); }, 4000); clearTimeout(temp); ?? – Josh Mc Jun 19 '12 at 04:00
  • 12
    What would happen if topicId gets changed after the timeout was set, but before the function is called? – pilau Nov 02 '12 at 00:19
  • 23
    @pilau that's exactly my problem: if the variables used in the anonymous function change before the timeout (such as in a for loop) then it will also change inside the function. So in my example setting 5 different timeouts in a for loop actually ended up using the same variables. Be careful when using this answer! – Cristian May 08 '13 at 08:27
  • So this method does not account for value changes before the function call - it will always use the original value passed to `setTimeout`? – pilau May 08 '13 at 09:23
  • You need a closure in order to make this work consistently as intended. – Tom Auger May 17 '13 at 20:22
  • 10
    @pilau using another closure will help topicId=12; function postinsql(topicId){ console.log(topicId); } function setTimeOutWithClosure(topicId){ setTimeout(function() { postinsql(topicId); }, 1000) } setTimeOutFunction(topicId); topicId=13; – Halis Yılboğa Dec 23 '13 at 08:31
  • @Miles In regards to your first comment, it is technically not a DOM method, it is a WOM method. – SirPython Feb 09 '15 at 23:39
  • 1
    @HalisYılboğa Thanks friend, years later I've found your comment and it's helped me. – Jack Hales Oct 12 '17 at 05:51
  • If `setTimeout(function() { postinsql(topicId); }, 4000)` or `setTimeout(function(topicId) { postinsql(topicId); }, 4000)` did not work. Use `setTimeout(function(topicId) { postinsql(topicId); } (topicId), 4000)` – vee Dec 02 '18 at 02:31
  • Why did you pass a `null` in `setTimeout(postinsql.bind(null, topicId), 4000);` – Shayan Sep 09 '20 at 18:57
  • 1
    Even better than the `bind` method, nowadays you can provide arguments to the [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) function: `setTimeout(postinsql, 4000, topicId)`. Though, doesn't work on IE below version 10. – Gras Double Apr 15 '21 at 01:08
801

In modern browsers (ie IE11 and beyond), the "setTimeout" receives a third parameter that is sent as parameter to the internal function at the end of the timer.

Example:

var hello = "Hello World";
setTimeout(alert, 1000, hello);

More details:

jfunk
  • 3,257
  • 2
  • 26
  • 31
Fabio Phms
  • 8,645
  • 1
  • 13
  • 9
  • 64
    I'm not sure why this answer wasn't selected as the best. Using an anonymous function works, sure, but if you can simply pass a third parameter into the original setTimeout function call... why not? – Kris Schouw Sep 21 '11 at 17:36
  • 55
    Because it doesn't work in versions of IE still very much in the wild. – Aaron Feb 08 '12 at 06:32
  • It also seems like it isn't an official part of the spec. Additionall, w3cschools has the third parameter as the language to run the function as. – Kevin Schroeder May 14 '12 at 21:07
  • 4
    This answer actually made me able to pass an event object, the other methods didn't. I already had an anonymous function. – Glenn Plas Oct 10 '12 at 22:40
  • 29
    By far better answer. If you have code that modifies your parameter between "setTimeout" call and actual execution of the anonymous function - the anonymous function will receive modified value, not what it was at the time of setTimeout call. e.g.: for(var i = 0; i < 100; i++) { setTimeout(function() { console.write(i); }, 0); } this will log "100" a 100 times (tested on FF). Current answer helps avoiding this. – root Dec 14 '12 at 17:21
  • Look at the link in the comment, it has a shim for older IE versions. This is more correct than the accepted answer, which doesn't preserve the context of when the timeout was initially called. Typically when you pass a string into settimeout its because you are trying to preserve the current state of when the timeout was called, not the state of when it is fired. – wowo_999 Sep 24 '13 at 19:07
  • https://developer.mozilla.org/en/docs/Web/API/window.setTimeout here has very detailed explanation of this function. You can find a correct way(works in IE) to pass parameters into the anonymous callback function. – raven Aug 22 '14 at 08:06
  • 1
    Acording to https://developer.mozilla.org/es/docs/Web/API/WindowTimers/setTimeout the callback arguments for Internet Explorer is only supported in versions >=10, be carefull as in many sites ie8 and ie9 still gets some relevant share. – le0diaz Jun 03 '15 at 16:09
  • To enable this Internet Explorer below version 10, use the code in this answer: http://stackoverflow.com/a/12404562/2211053 – Gavin Feb 15 '16 at 11:36
  • Anyone can give me an easy explanation why setTimeout(postinsql(topicId),4000); is not working? – Marek Nov 15 '17 at 20:16
  • 1
    The best answer. Working like a charm. – Skylin R Apr 24 '18 at 10:02
  • 1
    @Marek - because you're not passing the function `postinsql` to the `setTimeout`, you're calling it and passing its return value to `setTimeout` – BryanGrezeszak Jun 17 '18 at 20:18
  • Oh my GOD! I was messing around with this in console while I was on Medium, and they overwrite setTimeout with a custom function that works but doesn't pass the further parameters. I thought it was removed from Chrome without a warning or something xD – Mihail Malostanidis Aug 15 '18 at 13:12
  • This should indeed be the accepted answer. Okay, not for "older browser" nerds, but definitely the best for modern browsers. Preserving the original value without any additional manipulation (extra closure, JSON.stringify-parse for scalar values, etc.) of the parameters is the greatest help!! – Jay Dadhania Oct 13 '19 at 16:57
  • 1
    You can remove the part about "modern browsers", today [all major browsers support it](https://caniuse.com/#feat=mdn-api_windoworworkerglobalscope_settimeout_supports_parameters_for_callback) (I tested it on Safari 12 so it works there also). – Donald Duck Aug 06 '20 at 16:34
166

After doing some research and testing, the only correct implementation is:

setTimeout(yourFunctionReference, 4000, param1, param2, paramN);

setTimeout will pass all extra parameters to your function so they can be processed there.

The anonymous function can work for very basic stuff, but within instance of a object where you have to use "this", there is no way to make it work. Any anonymous function will change "this" to point to window, so you will lose your object reference.

Jiri Vetyska
  • 1,778
  • 1
  • 10
  • 6
  • 26
    It is with sadness in my heart that I must inform: this doesn't work in internet explorer. :/ All the extra params come through as undefined. – Amalgovinus Apr 24 '13 at 00:39
  • "within instance of a object where you have to use "this", there is no way to make it work." - not true. You can make the `this` reference work, even without using `bind` (supported from IE9 onwards). You just pass the following anonymous function: `function() { someObject.someMethod() }`. – Myrne Stol May 28 '13 at 21:26
  • 8
    I just use `var that = this; setTimeout( function() { that.foo(); }, 1000);` – Ed Williams Jun 07 '13 at 06:41
  • 2
    This is correct, and it is specified in HTML5. http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-setinterval – Garrett Jan 13 '14 at 00:15
  • 6
    This is exactly the same answer as [Fabio's](http://stackoverflow.com/a/7503942/1269037). – Dan Dascalescu Apr 17 '15 at 07:16
  • 1
    Acording to https://developer.mozilla.org/es/docs/Web/API/WindowTimers/setTimeout the callback arguments for Internet Explorer is only supported in versions >=10, be carefull as in many sites ie8 and ie9 still gets some relevant share. – le0diaz Jun 03 '15 at 16:09
47

This is a very old question with an already "correct" answer but I thought I'd mention another approach that nobody has mentioned here. This is copied and pasted from the excellent underscore library:

_.delay = function(func, wait) {
  var args = slice.call(arguments, 2);
  return setTimeout(function(){ return func.apply(null, args); }, wait);
};

You can pass as many arguments as you'd like to the function called by setTimeout and as an added bonus (well, usually a bonus) the value of the arguments passed to your function are frozen when you call setTimeout, so if they change value at some point between when setTimeout() is called and when it times out, well... that's not so hideously frustrating anymore :)

Here's a fiddle where you can see what I mean.

brasofilo
  • 23,940
  • 15
  • 86
  • 168
David Meister
  • 3,444
  • 1
  • 23
  • 27
  • 8
    That answer actually works but you seem to have some library that I don't. Here's the little fix for it to work: instead of slice.call, use Array.prototype.slice.call(arguments, 2) – Melanie Oct 03 '13 at 16:44
  • 7
    @Melanie "some library"? I said in the answer that it's the underscore library - http://underscorejs.org/. But yes, Array.prototype.slice is aliased to slice inside that library, so you have to do that yourself if you're not using it, good spot :) – David Meister Oct 04 '13 at 14:33
40

I recently came across the unique situation of needing to use a setTimeout in a loop. Understanding this can help you understand how to pass parameters to setTimeout.

Method 1

Use forEach and Object.keys, as per Sukima's suggestion:

var testObject = {
    prop1: 'test1',
    prop2: 'test2',
    prop3: 'test3'
};

Object.keys(testObject).forEach(function(propertyName, i) {
    setTimeout(function() {
        console.log(testObject[propertyName]);
    }, i * 1000);
});

I recommend this method.

Method 2

Use bind:

var i = 0;
for (var propertyName in testObject) {
    setTimeout(function(propertyName) {
        console.log(testObject[propertyName]);
    }.bind(this, propertyName), i++ * 1000);
}

JSFiddle: http://jsfiddle.net/MsBkW/

Method 3

Or if you can't use forEach or bind, use an IIFE:

var i = 0;
for (var propertyName in testObject) {
    setTimeout((function(propertyName) {
        return function() {
            console.log(testObject[propertyName]);
        };
    })(propertyName), i++ * 1000);
}

Method 4

But if you don't care about IE < 10, then you could use Fabio's suggestion:

var i = 0;
for (var propertyName in testObject) {
    setTimeout(function(propertyName) {
        console.log(testObject[propertyName]);
    }, i++ * 1000, propertyName);
}

Method 5 (ES6)

Use a block scoped variable:

let i = 0;
for (let propertyName in testObject) {
    setTimeout(() => console.log(testObject[propertyName]), i++ * 1000);
}

Though I would still recommend using Object.keys with forEach in ES6.

Community
  • 1
  • 1
David Sherret
  • 82,097
  • 24
  • 165
  • 160
  • 2
    Note: `.bind` will not work for IE8 and below [ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Browser_compatibility ]. I ended up using Schien's solution: http://stackoverflow.com/a/21213723/1876899 – cjspurgeon Apr 22 '14 at 18:35
  • 1
    If your in an environment that uses `bind` then your also in an environment that offers `Object.keys` and `forEach`. You can loose the for loop and get a "free" (as in two birds with one stone free not resource free) function scope in the process. – Sukima Jul 08 '14 at 12:08
  • @David Sherret in case you haven't used it before, definitely check out the `async` library (https://github.com/caolan/async). We use it extensively in Sails and have had great results for the past 2 years. It provides methods in both parallel and in series for asynchronous `forEach`, `map`, `reduce`, etc. – mikermcneil Oct 23 '15 at 12:26
27

Hobblin already commented this on the question, but it should be an answer really!

Using Function.prototype.bind() is the cleanest and most flexible way to do this (with the added bonus of being able to set the this context):

setTimeout(postinsql.bind(null, topicId), 4000);

For more information see these MDN links:
https://developer.mozilla.org/en/docs/DOM/window.setTimeout#highlighter_547041 https://developer.mozilla.org/en/docs/JavaScript/Reference/Global_Objects/Function/bind#With_setTimeout

Mark Amery
  • 110,735
  • 57
  • 354
  • 402
dain
  • 6,183
  • 1
  • 34
  • 42
17

Some answers are correct but convoluted.

I am answering this again, 4 years later, because I still run into overly complex code to solve exactly this question. There IS an elegant solution.

First of all, do not pass in a string as the first parameter when calling setTimeout because it effectively invokes a call to the slow "eval" function.

So how do we pass in a parameter to a timeout function? By using closure:

settopic=function(topicid){
  setTimeout(function(){
    //thanks to closure, topicid is visible here
    postinsql(topicid);
  },4000);
}

...
if (xhr.readyState==4){
  settopic(xhr.responseText);
}

Some have suggested using anonymous function when calling the timeout function:

if (xhr.readyState==4){
  setTimeout(function(){
    settopic(xhr.responseText);
  },4000);
}

The syntax works out. But by the time settopic is called, i.e. 4 seconds later, the XHR object may not be the same. Therefore it's important to pre-bind the variables.

Community
  • 1
  • 1
Schien
  • 3,493
  • 1
  • 13
  • 27
  • 1
    +1 for a readable solution, slightly different to mine. While you have the setTimeout inside the settopic function, I have the fDelayed (your settopic) function inside the setTimeout function. – Dominic Jan 20 '14 at 09:02
14

You can pass the parameter to the setTimeout callback function as:

setTimeout(function, milliseconds, param1, param2, ...)

eg.

function myFunction() {
  setTimeout(alertMsg, 3000, "Hello");
}

function alertMsg(message) {
    alert(message)
}
Jatin Verma
  • 183
  • 1
  • 10
  • 1
    Can anyone tell me why this answer isn't the preferred one? this is the most simple way in my opinion! As simple as `setTimeout( (p) => { console.log(p); }, 1000, "hi" );` – Mazhar Zandsalimi Oct 20 '19 at 10:22
  • 2
    Yeah! This should be the accepted answer. From MDN: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout – Han Dec 26 '19 at 09:33
14

I know its been 10 yrs since this question was asked, but still, if you have scrolled till here, i assume you're still facing some issue. The solution by Meder Omuraliev is the simplest one and may help most of us but for those who don't want to have any binding, here it is:

  1. Use Param for setTimeout
setTimeout(function(p){
//p == param1
},3000,param1);
  1. Use Immediately Invoked Function Expression(IIFE)
let param1 = 'demon';
setTimeout(function(p){
    // p == 'demon'
},2000,(function(){
    return param1;
})()
);
  1. Solution to the question
function statechangedPostQuestion()
{
  //alert("statechangedPostQuestion");
  if (xmlhttp.readyState==4)
  {
    setTimeout(postinsql,4000,(function(){
        return xmlhttp.responseText;
    })());
  }
}

function postinsql(topicId)
{
  //alert(topicId);
}
Alpesh Patil
  • 460
  • 4
  • 7
11

Replace

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

with

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

or better still, replace the string expression with an anonymous function

 setTimeout(function () { 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
  • 117,566
  • 29
  • 193
  • 253
  • 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); – shuckster Jul 27 '09 at 21:20
  • 2
    @brownstone: That's incorrect. The string will be evaluated when the timeout fires. – Miles Jul 27 '09 at 23:09
11

My answer:

setTimeout((function(topicId) {
  return function() {
    postinsql(topicId);
  };
})(topicId), 4000);

Explanation:

The anonymous function created returns another anonymous function. This function has access to the originally passed topicId, so it will not make an error. The first anonymous function is immediately called, passing in topicId, so the registered function with a delay has access to topicId at the time of calling, through closures.

OR

This basically converts to:

setTimeout(function() {
  postinsql(topicId); // topicId inside higher scope (passed to returning function)
}, 4000);

EDIT: I saw the same answer, so look at his. But I didn't steal his answer! I just forgot to look. Read the explanation and see if it helps to understand the code.

  • This is the best answer. A lot of these solutions will not even honor the timeout. However, why are you wrapping the first anonymous function in parenthesis? I don't think they are necessary to accomplish this. – Robert Henderson Mar 01 '18 at 23:40
  • this is the best answer , but had to do a clone because when values like `topicId` gets altered the value in timeout changes as well. A clone fixed it – pariola Jul 04 '18 at 21:45
7

The easiest cross browser solution for supporting parameters in setTimeout:

setTimeout(function() {
    postinsql(topicId);
}, 4000)

If you don't mind not supporting IE 9 and lower:

setTimeout(postinsql, 4000, topicId);

setTimeout desktop browser compatibility

setTimeout mobile browser compatibility

https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout

Michael J. Calkins
  • 30,148
  • 14
  • 58
  • 89
4

I know it's old but I wanted to add my (preferred) flavour to this.

I think a pretty readable way to achieve this is to pass the topicId to a function, which in turn uses the argument to reference the topic ID internally. This value won't change even if topicId in the outside will be changed shortly after.

var topicId = xmlhttp.responseText;
var fDelayed = function(tid) {
  return function() {
    postinsql(tid);
  };
}
setTimeout(fDelayed(topicId),4000);

or short:

var topicId = xmlhttp.responseText;
setTimeout(function(tid) {
  return function() { postinsql(tid); };
}(topicId), 4000);
Dominic
  • 825
  • 8
  • 13
4

The answer by David Meister seems to take care of parameters that may change immediately after the call to setTimeout() but before the anonymous function is called. But it's too cumbersome and not very obvious. I discovered an elegant way of doing pretty much the same thing using IIFE (immediately inviked function expression).

In the example below, the currentList variable is passed to the IIFE, which saves it in its closure, until the delayed function is invoked. Even if the variable currentList changes immediately after the code shown, the setInterval() will do the right thing.

Without this IIFE technique, the setTimeout() function will definitely get called for each h2 element in the DOM, but all those calls will see only the text value of the last h2 element.

<script>
  // Wait for the document to load.
  $(document).ready(function() {
  $("h2").each(function (index) {

    currentList = $(this).text();

    (function (param1, param2) {
        setTimeout(function() {
            $("span").text(param1 + ' : ' + param2 );
        }, param1 * 1000);

    })(index, currentList);
  });
</script>
Gurjeet Singh
  • 1,897
  • 1
  • 20
  • 22
4

In general, if you need to pass a function as a callback with specific parameters, you can use higher order functions. This is pretty elegant with ES6:

const someFunction = (params) => () => {
  //do whatever
};

setTimeout(someFunction(params), 1000);

Or if someFunction is first order:

setTimeout(() => someFunction(params), 1000); 
John Hartman
  • 315
  • 2
  • 9
3

How i resolved this stage ?

just like that :

setTimeout((function(_deepFunction ,_deepData){
    var _deepResultFunction = function _deepResultFunction(){
          _deepFunction(_deepData);
    };
    return _deepResultFunction;
})(fromOuterFunction, fromOuterData ) , 1000  );

setTimeout wait a reference to a function, so i created it in a closure, which interprete my data and return a function with a good instance of my data !

Maybe you can improve this part :

_deepFunction(_deepData);

// change to something like :
_deepFunction.apply(contextFromParams , args); 

I tested it on chrome, firefox and IE and it execute well, i don't know about performance but i needed it to be working.

a sample test :

myDelay_function = function(fn , params , ctxt , _time){
setTimeout((function(_deepFunction ,_deepData, _deepCtxt){
            var _deepResultFunction = function _deepResultFunction(){
                //_deepFunction(_deepData);
                _deepFunction.call(  _deepCtxt , _deepData);
            };
        return _deepResultFunction;
    })(fn , params , ctxt)
, _time) 
};

// the function to be used :
myFunc = function(param){ console.log(param + this.name) }
// note that we call this.name

// a context object :
myObjet = {
    id : "myId" , 
    name : "myName"
}

// setting a parmeter
myParamter = "I am the outer parameter : ";

//and now let's make the call :
myDelay_function(myFunc , myParamter  , myObjet , 1000)

// this will produce this result on the console line :
// I am the outer parameter : myName

Maybe you can change the signature to make it more complient :

myNass_setTimeOut = function (fn , _time , params , ctxt ){
return setTimeout((function(_deepFunction ,_deepData, _deepCtxt){
            var _deepResultFunction = function _deepResultFunction(){
                //_deepFunction(_deepData);
                _deepFunction.apply(  _deepCtxt , _deepData);
            };
        return _deepResultFunction;
    })(fn , params , ctxt)
, _time) 
};

// and try again :
for(var i=0; i<10; i++){
   myNass_setTimeOut(console.log ,1000 , [i] , console)
}

And finaly to answer the original question :

 myNass_setTimeOut( postinsql, 4000, topicId );

Hope it can help !

ps : sorry but english it's not my mother tongue !

Anonymous0day
  • 2,662
  • 1
  • 11
  • 15
3

this works in all browsers (IE is an oddball)

setTimeout( (function(x) {
return function() {
        postinsql(x);
    };
})(topicId) , 4000);
user3756459
  • 139
  • 2
3

Note that the reason topicId was "not defined" per the error message is that it existed as a local variable when the setTimeout was executed, but not when the delayed call to postinsql happened. Variable lifetime is especially important to pay attention to, especially when trying something like passing "this" as an object reference.

I heard that you can pass topicId as a third parameter to the setTimeout function. Not much detail is given but I got enough information to get it to work, and it's successful in Safari. I don't know what they mean about the "millisecond error" though. Check it out here:

http://www.howtocreate.co.uk/tutorials/javascript/timers

billy
  • 31
  • 1
3

if you want to pass variable as param lets try this

if requirement is function and var as parmas then try this

setTimeout((param1,param2) => { 
     alert(param1 + param2);
     postinsql(topicId);
},2000,'msg1', 'msg2')

if requirement is only variables as a params then try this

setTimeout((param1,param2) => { alert(param1 + param2) },2000,'msg1', 'msg2')

You can try this with ES5 and ES6

mad Man
  • 306
  • 3
  • 7
3

setTimeout is part of the DOM defined by WHAT WG.

https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html

The method you want is:—

handle = self.setTimeout( handler [, timeout [, arguments... ] ] )

Schedules a timeout to run handler after timeout milliseconds. Any arguments are passed straight through to the handler.

setTimeout(postinsql, 4000, topicId);

Apparently, extra arguments are supported in IE10. Alternatively, you can use setTimeout(postinsql.bind(null, topicId), 4000);, however passing extra arguments is simpler, and that's preferable.

Historical factoid: In days of VBScript, in JScript, setTimeout's third parameter was the language, as a string, defaulting to "JScript" but with the option to use "VBScript". https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa741500(v%3Dvs.85)

Garrett
  • 2,739
  • 1
  • 17
  • 16
2

You can try default functionality of 'apply()' something like this, you can pass more number of arguments as your requirement in the array

function postinsql(topicId)
{
  //alert(topicId);
}
setTimeout(
       postinsql.apply(window,["mytopic"])
,500);
Vishnu Prasanth G
  • 845
  • 10
  • 11
1

You have to remove quotes from your setTimeOut function call like this:

setTimeout(postinsql(topicId),4000);
jyr
  • 616
  • 6
  • 18
0

@Jiri Vetyska thanks for the post, but there is something wrong in your example. I needed to pass the target which is hovered out (this) to a timed out function and I tried your approach. Tested in IE9 - does not work. I also made some research and it appears that as pointed here the third parameter is the script language being used. No mention about additional parameters.

So, I followed @meder's answer and solved my issue with this code:

$('.targetItemClass').hover(ItemHoverIn, ItemHoverOut);

function ItemHoverIn() {
 //some code here
}

function ItemHoverOut() {
    var THIS = this;
    setTimeout(
        function () { ItemHoverOut_timeout(THIS); },
        100
    );
}
function ItemHoverOut_timeout(target) {
    //do something with target which is hovered out
}

Hope, this is usefull for someone else.

Vladislav
  • 2,202
  • 20
  • 40
0

As there is a problem with the third optonal parameter in IE and using closures prevents us from changing the variables (in a loop for example) and still achieving the desired result, I suggest the following solution.

We can try using recursion like this:

var i = 0;
var hellos = ["Hello World1!", "Hello World2!", "Hello World3!", "Hello World4!", "Hello World5!"];

if(hellos.length > 0) timeout();

function timeout() {                
    document.write('<p>' + hellos[i] + '<p>');
    i++;
    if (i < hellos.length)
        setTimeout(timeout, 500);
}

We need to make sure that nothing else changes these variables and that we write a proper recursion condition to avoid infinite recursion.

0

// These are three very simple and concise answers:

function fun() {
    console.log(this.prop1, this.prop2, this.prop3);
}

let obj = { prop1: 'one', prop2: 'two', prop3: 'three' };

let bound = fun.bind(obj);

setTimeout(bound, 3000);

 // or

function funOut(par1, par2, par3) {

  return function() { 

    console.log(par1, par2, par3);

  }
};

setTimeout(funOut('one', 'two', 'three'), 5000);

 // or

let funny = function(a, b, c) { console.log(a, b, c); };

setTimeout(funny, 2000, 'hello', 'worldly', 'people');
Rich
  • 17
  • 4
-2

I think you want:

setTimeout("postinsql(" + topicId + ")", 4000);
  • 1
    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. Apr 29 '10 at 18:00
  • 6
    Let's suppose that topicId is a function... Or an object. This won't work ! – Serafeim Nov 23 '11 at 13:41
  • If you really want to proceed with this method, use `JSON.stringify` for regular objects and arrays, and then use `JSON.parse` inside the function. However, all behavior will be lost if the object has methods. – DarthCadeus Dec 20 '18 at 03:15
-2

// These are three very simple and concise answers:

function fun() {
    console.log(this.prop1, this.prop2, this.prop3);
}

let obj = { prop1: 'one', prop2: 'two', prop3: 'three' };

let bound = fun.bind(obj);

setTimeout(bound, 3000);

 // or

function funOut(par1, par2, par3) {

  return function() { 

    console.log(par1, par2, par3);

  }
};

setTimeout(funOut('one', 'two', 'three'), 5000);

 // or

let funny = function(a, b, c) { console.log(a, b, c); };

setTimeout(funny, 2000, 'hello', 'worldly', 'people');
-2

Answering the question but by a simple addition function with 2 arguments.

var x = 3, y = 4;

setTimeout(function(arg1, arg2) { 
      delayedSum(arg1, arg2);
}(x, y), 1000);

function delayedSum(param1, param2) {
     alert(param1 + param2); // 7
}
SridharKritha
  • 5,151
  • 2
  • 34
  • 32
  • This doesn't work because the function is invoked immediately as it's defined, it does not use the timeout value. Do not use this method. – qJake Aug 19 '20 at 15:42