2010-01-10 21 views
14

Aquí está mi problema. Tengo esta función para probar servidores proxy.¿Por qué mi llamada de función que debería ser programada por setTimeout se ejecuta inmediatamente?

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

Quiero la función 'doRequest()' que se llamará en aproximadamente 10 segundos de intervalo, pero incluso con el setTimeout() las funciones se llaman inmediatamente.

Cualquier idea es bienvenida, gracias.

PD: Incluso si pongo un valor arbitrario para 'proxytimout' no tiene ningún efecto.

Respuesta

13

Al dar la función a la setTimeout en esa forma, se ejecuta la función en lugar de pasar a la setTimeout. Usted tiene tres alternativas para hacer que funcione:

Dale primero la función, entonces el tiempo de espera y los parámetros como los últimos argumentos:

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

o simplemente escribir una cadena que será evaluada:

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

El tercer estilo es pasar una función anónima que llama a la función. Nótese que en este caso, tiene que hacerlo en un cierre para evitar que los valores cambien en el bucle, por lo que se pone un poco complicado:

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

El segundo formato es un poco hacky, pero funciona, sin embargo, si los argumentos son valores escalares (strings, ints, etc.). El tercer formato es poco claro, por lo que en este caso la primera opción obviamente funcionará mejor para usted.

+3

Corrígeme si me equivoco, pero como esto sucede dentro de un ciclo, el segundo método que hayas dado no funcionará. El valor de 'proxy' cambiará porque no se ha creado ningún cierre. – nickf

+0

@nickf: estaba a punto de decir eso. Además, la tercera opción infringe 'eval is evil'. – SLaks

+0

@nickf, eres cierto, pasé por alto ese punto. He actualizado mi respuesta. –

0

Esta línea aquí está el problema:

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

Escribir doRequest() es en realidad la llamada a la función. Lo que quiere es pasar la función en sí:

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

Está mal entendiendo la función setTimeout.

La función setTimeout toma una función y la ejecuta más tarde.
Al escribir setTimeout(doRequest(url,proxys[proxy]), proxytimeout), llama a la función doRequest (inmediatamente) y pasa el resultado (suponiendo que devuelve otra función) al setTimeout.

lo necesario para pasar parámetros doRequest 's a setTimeout, así:

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

Esto pasará setTimeout la función doRequest sí mismo (sin llamar primero), y también pasará que los parámetros para dar a doRequest cuando finalmente lo llame.

Cuestiones relacionadas