How can I pass a parameter to a setTimeout() callb

2018-12-31 03:33发布

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?

21条回答
明月照影归
2楼-- · 2018-12-31 03:52

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.

查看更多
永恒的永恒
3楼-- · 2018-12-31 03:52

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

查看更多
余生无你
4楼-- · 2018-12-31 03:52

I think you want:

setTimeout("postinsql(" + topicId + ")", 4000);
查看更多
何处买醉
5楼-- · 2018-12-31 03:56
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);
查看更多
若你有天会懂
6楼-- · 2018-12-31 03:56

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); 
查看更多
笑指拈花
7楼-- · 2018-12-31 03:58

In modern browsers, 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:

查看更多
登录 后发表回答