我有一些JavaScript代码,看起来像:

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

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

我得到一个错误,topicId没有定义 在我使用setTimeout()函数之前,一切都在工作。

我希望我的postinsql(topicId)函数在一段时间后被调用。 我该怎么办?


当前回答

由于IE中的第三个可选参数有问题,并且使用闭包阻止我们改变变量(例如在循环中),但仍然达到预期的结果,我建议以下解决方案。

我们可以尝试像这样使用递归:

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);
}

我们需要确保没有其他东西改变这些变量,并且我们写了一个适当的递归条件来避免无限递归。

其他回答

//这是三个非常简单明了的答案:

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');

//Some function, with some arguments, that need to run with arguments var a = function a(b, c, d, e){console.log(b, c, d, e);} //Another function, where setTimeout using for function "a", this have the same arguments var f = function f(b, c, d, e){ setTimeout(a.apply(this, arguments), 100);} f(1,2,3,4); //run //Another function, where setTimeout using for function "a", but some another arguments using, in different order var g = function g(b, c, d, e){ setTimeout(function(d, c, b){a.apply(this, arguments);}, 100, d, c, b);} g(1,2,3,4);

setTimeout是WHAT WG定义的DOM的一部分。

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

方法为:-

Handle = self。setTimeout(处理程序[,timeout[,参数…]]) 在超时毫秒后安排一个超时运行处理程序。任何 参数直接传递给处理程序。

setTimeout(postinsql, 4000, topicId);

显然,IE10支持额外的参数。或者,您也可以使用setTimeout(postinsql。bind(null, topicId), 4000);,但是传递额外的参数更简单,这是更可取的。

历史事实:在VBScript时代,在JScript中,setTimeout的第三个参数是语言,作为一个字符串,默认为“JScript”,但可以选择使用“VBScript”。https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa741500 (v % 3 dvs.85)

David Meister的回答似乎考虑到了在调用setTimeout()之后、匿名函数调用之前可能立即改变的参数。但这太麻烦了,而且不太明显。我发现了一种优雅的方法,可以使用IIFE(立即调用的函数表达式)完成几乎相同的事情。

在下面的示例中,currentList变量被传递给IIFE, IIFE将其保存在闭包中,直到调用延迟函数。即使变量currentList在代码显示后立即改变,setInterval()也会做正确的事情。

如果没有这种IIFE技术,setTimeout()函数肯定会为DOM中的每个h2元素调用,但所有这些调用都只能看到最后一个h2元素的文本值。

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

有些答案是正确的,但令人费解。

四年后,我再次回答这个问题,因为我仍然会遇到过于复杂的代码来解决这个问题。有一个优雅的解决方案。

首先,在调用setTimeout时不要传入一个字符串作为第一个参数,因为它有效地调用了对缓慢的“eval”函数的调用。

那么如何将参数传递给超时函数呢?通过使用闭包:

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

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

一些人建议在调用timeout函数时使用匿名函数:

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

语法是正确的。但是当settopic被调用时,也就是4秒之后,XHR对象可能就不一样了。因此,预绑定变量非常重要。