2011-04-29 33 views
30

Esto podría sonar como una pregunta realmente novato, pero eso es porque soy bastante nuevo en JS. No pude encontrar ninguna información sobre esto en ninguna parte, así que pensé en preguntarle a la comunidad.JavaScript Infinite Loop?

¿Cómo hago un ciclo infinito en JavaScript? Estoy tratando de hacer una presentación de diapositivas, que he estado trabajando, pero no puedo hacer que se repita. Ni siquiera puedo hacer que se repita dos veces.

El código que estoy usando en este momento es

window.onload = function start() { 
    slide(); 
} 
function slide() { 
    var num = 0; 
    for (num=0;num<=10;num++) { 
     setTimeout("document.getElementById('container').style.marginLeft='-600px'",3000); 
     setTimeout("document.getElementById('container').style.marginLeft='-1200px'",6000); 
     setTimeout("document.getElementById('container').style.marginLeft='-1800px'",9000); 
     setTimeout("document.getElementById('container').style.marginLeft='0px'",12000); 
    } 
} 

Sin la cosa por allí, lo hace ir a través de una sola vez. Cuando lo puse, hace que Firefox se bloquee o simplemente se repite una vez. Estoy seguro de que esto es algo realmente simple de hacer, e incluso si tiene que ser un bucle de 1,000,000 de veces o algo en lugar de infinito, eso funcionaría bien para mí.

Además, no quiero usar jQuery o algo que alguien más haya creado. Estoy aprendiendo JavaScript, y esto es en parte para ayudarme a aprender, y en parte porque estoy tratando de hacer tantos sistemas basados ​​en HTML5 como pueda.

EDIT: Creo que la razón por la que está congelado es porque ejecuta el código de una vez, y luego simplemente lo almacena en un caché o algo así. Lo que quiero que haga es pasar esto una vez, luego comenzar de nuevo en la parte superior, que es lo que siempre he pensado en los bucles. En scripts "por lotes" (símbolo del sistema), esto se puede hacer con un comando "GOTO". No sé si hay un equivalente en JS o no, pero ese es realmente mi objetivo.

+4

¿Qué tiene que ver el uso de jQuery con el uso de HTML5? – Ender

+5

jQuery no impide que aprenda Javascript. Está ahí para ayudar a ocultar las diferencias (demasiadas) en las implementaciones de JavaScript de cada navegador. Créame, todavía tendrá las manos muy sucias con Javascript, incluso con la ayuda de jquery. –

+5

Ah, y la mayoría de los navegadores no le permiten ejecutar un bucle infinito en javascript. Sería demasiado fácil hacer ataques DoS a las personas si lo hicieran. Después de un cierto tiempo/número de operaciones, mostrarán diálogos de advertencia para que el script se comporte mal y le permitirán al usuario abortar el script. –

Respuesta

52

El enfoque correcto es utilizar un solo temporizador. Usando setInterval, se puede lograr lo que quiere de la siguiente manera:

window.onload = function start() { 
    slide(); 
} 
function slide() { 
    var num = 0, style = document.getElementById('container').style; 
    window.setInterval(function() { 
     // increase by num 1, reset to 0 at 4 
     num = (num + 1) % 4; 

     // -600 * 1 = -600, -600 * 2 = -1200, etc 
     style.marginLeft = (-600 * num) + "px"; 
    }, 3000); // repeat forever, polling every 3 seconds 
} 
+0

Esto funcionó, gracias :) Esto era realmente lo que estaba tratando de hacer originalmente, pero no pude encontrar la manera de agregarle marginLeft. EDITAR: Esta respuesta es EXACTAMENTE lo que yo quería, también, porque solo requiere una edición rápida si quiero agregar como 20 diapositivas. Gracias, esto es genial. – JacobTheDev

+0

@Rev: feliz de ayudar, hubo muchas respuestas confusas aquí, así que pensé que sería una buena idea arrojar mi solución :-) –

+0

@Andy Esto se parece al mío, con la excepción más importante (creo) que el suyo está escrito más elegante :) –

-2

probar esto:

window.onload = function start() { 
    slide(); 
} 
function slide() { 
    setInterval("document.getElementById('container').style.marginLeft='-600px'",3000); 
    setInterval("document.getElementById('container').style.marginLeft='-1200px'",6000); 
    setInterval("document.getElementById('container').style.marginLeft='-1800px'",9000); 
    setInterval("document.getElementById('container').style.marginLeft='0px'",12000); 
} 

setInterval es básicamente un 'bucle infinito' y no lo puedo negro el navegador. espera el tiempo requerido, luego se vuelve a

+3

Eso hará que las devoluciones de llamadas de intervalo se superpongan entre sí y produzcan un efecto no deseado. –

+0

@andy eso es mejor que muchos muchos setTimeouts superpuestos 10X – Neal

+5

@Neal: los setTimeouts originales no se superponen - son secuenciales en 3000, 6000, 9000 etc. Con su enfoque, el primer temporizador disparará a 3000 ... 6000. .. 9000 ... cuando debería disparar a 3000 ... 15000 ... 27000 ... etc. –

0

Puede iterar infinitamente con facilidad a través de la recursión.

function it_keeps_going_and_going_and_going() { 
    it_keeps_going_and_going_and_going(); 
} 

it_keeps_going_and_going_and_going() 
+3

Esto no es infinito, pero en su lugar se bloqueará después de un stackoverflow. – YoYoYonnY

0

La clave no es programar todas las fotografías a la vez, sino programar una próxima foto cada vez que se muestre una imagen.

var current = 0; 
var num_slides = 10; 
function slide() { 
    // here display the current slide, then: 

    current = (current + 1) % num_slides; 
    setTimeout(slide, 3000); 
} 

La alternativa es utilizar setInterval, que define la función que repetir periódicamente (en contraposición a setTimeout, que los horarios de la próxima aparición solamente.

17

Usted no quiere while(true), que encerrar a su . sistema

Lo que se quiere decir en lugar de un tiempo que establece un tiempo de espera en sí mismo, algo como esto:

function start() { 
    // your code here 
    setTimeout(start, 3000); 
} 

// boot up the first call 
start(); 
1

Está llamando al setTimeout() diez veces seguidas, por lo que todas caducan casi al mismo tiempo. Lo que realmente quiere es la siguiente:

window.onload = function start() { 
    slide(10); 
} 
function slide(repeats) { 
    if (repeats > 0) { 
     document.getElementById('container').style.marginLeft='-600px'; 
     document.getElementById('container').style.marginLeft='-1200px'; 
     document.getElementById('container').style.marginLeft='-1800px'; 
     document.getElementById('container').style.marginLeft='0px'; 
     window.setTimeout(
      function(){ 
      slide(repeats - 1) 
      }, 
      3000 
     ); 
    } 
} 

Para ello, será deslizante (10), que a su vez establecer el 3 segundos de tiempo de espera para llamar deslizante (9), que establecerá el tiempo de espera para llamar deslizamiento (8), etc. Cuando se llama a la diapositiva (0), no se configurarán más tiempos de espera.

+0

Esto anula el objetivo de una exposición fotográfica deslizante: ¡no se va a dejar el contenedor en su lugar por un período de tiempo prolongado antes de volver a moverlo a su origen! –

3

Perhps esto es lo que estás buscando.

var pos = 0; 
window.onload = function start() { 
    setTimeout(slide, 3000); 
} 
function slide() { 
    pos -= 600; 
    if (pos === -2400) 
    pos = 0; 
    document.getElementById('container').style.marginLeft= pos + "px"; 
    setTimeout(slide, 3000); 
} 
7

Aquí es una buena solución, ordenado para usted: (also see the live demo ->)

window.onload = function start() { 
    slide(); 
} 

function slide() { 
    var currMarg = 0, 
     contStyle = document.getElementById('container').style; 
    setInterval(function() { 
     currMarg = currMarg == 1800 ? 0 : currMarg + 600; 
     contStyle.marginLeft = '-' + currMarg + 'px'; 
    }, 3000); 
} 

Puesto que usted está tratando de aprender, permítanme explicar cómo esto funciona.

Primero declaramos dos variables: currMarg y contStyle. currMarg es un número entero que usaremos para rastrear/actualizar qué margen izquierdo debe tener el contenedor. Lo declaramos fuera de la función de actualización real (en un closure), de modo que pueda actualizarse continuamente/acceder sin perder su valor. contStyle es simplemente una variable de conveniencia que nos da acceso a los estilos de contenedores sin tener que ubicar el elemento en cada intervalo.

A continuación, utilizaremos setInterval para establecer una función que se debe llamar cada 3 segundos, hasta que le digamos que se detenga (hay un ciclo infinito, sin congelar el navegador). Funciona exactamente como setTimeout, excepto que ocurre infinitamente hasta que se cancela, en lugar de suceder una sola vez.

Pasamos un anonymous function a setInterval, que hará nuestro trabajo por nosotros. La primera línea es:

currMarg = currMarg == 1800 ? 0 : currMarg + 600; 

Esto es ternary operator. Asignará currMarg el valor de 0 si currMarg es igual a 1800, de lo contrario aumentará currMarg en 600.

Con la segunda línea, simplemente asignamos nuestro valor elegido a container s marginLeft, ¡y terminamos!

Nota: Para la demostración, cambié los valores negativos a positivo, por lo que el efecto sería visible.

+1

Bien descrito señor. –

+0

¡Por qué, gracias! Usted señor, es un erudito y un caballero. – Ender

+5

Pip pip! ¿Qué decir que celebramos nuestra buena salud por una pipa del mejor tabac, mi buen amigo? –