【问题标题】:Why is my function call that should be scheduled by setTimeout executed immediately? [duplicate]为什么我应该由 setTimeout 安排的函数调用立即执行? [复制]
【发布时间】:2011-01-03 11:29:03
【问题描述】:

这是我的问题。我有这个功能来测试代理服务器。

function crawl() {
    var oldstatus = document.getElementById('status').innerHTML;
    document.getElementById('status').innerHTML = oldstatus + "Crawler Started...<br />";
    var url = document.getElementById('url').value;
    var proxys = document.getElementById('proxys').value.replace(/\n/g,',');

    var proxys = proxys.split(",");

    for (proxy in proxys) {
        var proxytimeout = proxy*10000;
        setTimeout(doRequest(url,proxys[proxy]), proxytimeout);
    }
}

我希望以大约 10 秒的间隔调用“doRequest()”函数,但即使使用 setTimeout(),也会立即调用函数。

欢迎任何想法,谢谢。

PS:即使我为 'proxytimout' 设置了一个任意值,它也没有效果。

【问题讨论】:

    标签: javascript loops for-loop settimeout


    【解决方案1】:

    当您以该形式将函数提供给 setTimeout 时,该函数将被执行而不是传递给 setTimeout。您有三种方法可以让它发挥作用:

    首先给出函数,然后给出超时和参数作为最后一个参数:

    setTimeout(doRequest, proxytimeout, url, proxys[proxy]);
    

    或者只是写一个将被评估的字符串:

    setTimeout('doRequest('+url+','+proxys[proxy]+')', proxytimeout);
    

    第三种风格是传递一个调用函数的匿名函数。请注意,在这种情况下,您必须在闭包中执行此操作以防止值在循环中更改,因此有点棘手:

    (function(u, p, t) {
        setTimeout(function() { doRequest(u, p); }, t);
    })(url, proxys[proxy], proxytimeout);
    

    第二种格式有点老套,但如果参数是标量值(字符串、整数等),它仍然有效。第三种格式有点不清楚,所以在这种情况下,第一种选择显然最适合您。

    【讨论】:

    • 如果我错了,请纠正我,但是由于这是在循环中发生的,因此您提供的第二种方法将不起作用。 proxy 的值会改变,因为没有创建闭包。
    • @nickf:我正要这么说。此外,第三个选项违反了eval is evil
    • @nickf,你说得对,我忽略了这一点。我已经更新了我的答案。
    • 感谢您的大力帮助,这是一个令人难以置信的社区!
    • setTimeout(doRequest, proxytimeout, url, proxys[proxy]) 在 IE 中不起作用,对吧?
    【解决方案2】:

    这行是问题所在:

    setTimeout(doRequest(url,proxys[proxy]), proxytimeout);
    

    doRequest()其实就是调用函数。你想要的是传递函数本身:

    setTimeout(doRequest, proxytime, url, proxys[proxy]);
    

    【讨论】:

      【解决方案3】:

      您误解了setTimeout 函数。

      setTimeout 函数接受一个函数并稍后执行它。
      通过编写setTimeout(doRequest(url,proxys[proxy]), proxytimeout),您(立即)调用doRequest 函数,并将结果(假设它返回另一个函数)传递给setTimeout

      你需要将doRequest的参数传递给setTimeout,像这样:

      setTimeout(doRequest, proxytimeout, url, proxys[proxy]);
      

      这将传递setTimeoutdoRequest 函数本身(不先调用它),并且还将传递给doRequest 的参数,以便在它最终调用它时提供给doRequest

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-31
        相关资源
        最近更新 更多