views:

599

answers:

3

Here's my issue. I have this function to test proxy servers.

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

I want the 'doRequest()' function to be called in roughly 10 second intervals but even with the setTimeout() the functions are called immediately.

Any ideas are welcome, thanks.

PS: Even if I put an arbitrary value for 'proxytimout' it has no effect.

A: 

This line here is the problem:

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

Writing doRequest() is actually calling the function. What you want is to pass the function itself:

setTimeout(doRequest, proxytime, url, proxys[proxy]);
nickf
+3  A: 

As you give the function to the setTimeout in that form, the function is executed instead of passed to the setTimeout. You have three alternatives to make it work:

Give first the function, then the timeout and the parameters as the last arguments:

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

Or just write a string that will be evaluated:

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

Third style is to pass an anonymous function that calls the function. Note that in this case, you have to do it in a closure to prevent the values from changing in the loop, so it gets a bit tricky:

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

The second format is a bit hacky, but works nevertheless if the arguments are scalar values (strings, ints etc). The third format is a bit unclear, so in this case the first option will obviously work best for you.

Tatu Ulmanen
Correct me if I'm wrong, but since this is happening inside a loop, the second method you've given won't work. The value of `proxy` will change because there's no closure created.
nickf
@nickf: I was about to say that. Also, the third option violates `eval is evil`.
SLaks
@nickf, you're true, I overlooked that point. I've updated my answer.
Tatu Ulmanen
Thanks that's a huge help, this is an incredible community!
Ben
the setTimeout(doRequest, proxytimeout, url, proxys[proxy]) won't work in IE, right?
kenny
A: 

You're misunderstanding the setTimeout function.

The setTimeout function takes a function and executes it later.
By writing setTimeout(doRequest(url,proxys[proxy]), proxytimeout), you're _calling the doRequest function (immediately), and passing the result (assuming that it returns another function) to setTimeout.

You need to pass doRequest's parameters to setTimeout, like this:

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

This will pass setTimeout the doRequest function itself (without calling it first), and will also pass it the parameters to give to doRequest when it finally calls it.

SLaks