2010-01-19 68 views
6

¿Puede detener la ejecución de JavaScript sin bloquear el navegador? La forma en que normalmente detendría la ejecución es hacer un infinito while() -loop, pero en el caso de FireFox, bloquea el navegador hasta que el ciclo haya finalizado.Detener la ejecución de JavaScript sin bloquear el navegador

¿Cuál es su opinión sobre esto?


Estoy tratando de anular window.confirm() para implementar mi propio diálogo con HTML. Estoy haciendo esto para no tener que cambiar el código existente (es una base de código bastante grande).

Necesito ser capaz de detener la ejecución para permitir la entrada del usuario; a su vez devolver un valor lógico como la función confirman norma hace:

if (confirm("...")) 
{ 
    // user pressed "OK" 
} 
else 
{ 
    // user pressed "Cancel" 
} 



actualización

Que yo sepa; esto no se puede hacer usando setTimeout() o setInterval() ya que estas funciones ejecutan el código que se les da de forma asincrónica.

+2

'' setTimeout' y setInterval' * no * ejecutar código de forma asíncrona, que cuentan hacia abajo y luego agregue la función de devolución de llamada a una cola que se llama cuando el hilo queda inactivo. Las funciones en sí mismas se ejecutan sincrónicamente. –

+0

Vea también: http://stackoverflow.com/questions/2056747/javascript-puzzle-to-solve-window-confirm-divconfirmstrmessage –

+3

@Andy E - 'window.setTimeout' (y' window.setInterval') crea devoluciones de llamada asincrónicas . El flujo de programa normal continúa inmediatamente después de llamarlo y la devolución de llamada se ejecuta en una fecha posterior, dependiendo de la duración del temporizador. El hecho de que JavaScript es de un solo subproceso y la devolución de llamada, una vez que ha comenzado a ejecutarse, y bloquea la ejecución de otro código no impide que haya sido asíncrono. –

Respuesta

8

confirm()prompt() y alert() son funciones especiales: llaman al sandbox de JavaScript en el navegador y el navegador suspende la ejecución de JavaScript. No puede hacer lo mismo, ya que necesita construir su funcionalidad en JavaScript.

No creo que hay una gran manera de caer en un reemplazo sin hacer una reestructuración en la línea de:

myconfirmfunction(function() { 
    /* OK callback */ 
}, function() { 
    /* cancel callback */ 
}); 
+0

He actualizado mi pregunta. Echar un vistazo. – roosteronacid

2

la forma en que normalmente se debe detener la ejecución casi nunca ser un bucle while.

ruptura de su trabajo en partes, que llame con SetTimeout

cambiar esta situación:

DoSomeWork(); 
    Wait(1000); 
    var a = DoSomeMoreWork(); 
    Wait(1000); 
    DoEvenMoreWork(a); 

a esto:

DoSomeWork(); 
setTimeout(function() { 
    var a = DoSomeMoreWork(); 
    setTimeout(function() { 
     DoEvenMoreWork(a); 
    }, 1000); 
}, 1000); 
+0

He actualizado mi pregunta. Echar un vistazo. – roosteronacid

7

No se puede detener el hilo de eventos en JavaScript, por lo en su lugar, tiene que evitar el problema, generalmente mediante el uso de funciones de devolución de llamada. Estas son funciones que se ejecutan en un momento posterior, pero se pueden pasar como cualquier otro objeto en JavaScript. Es posible que esté familiarizado con ellos desde la programación AJAX. Así, por ejemplo:

doSomeThing(); 
var result = confirm("some importart question"); 
doSomeThingElse(result); 

se convertiría en:

doSomeThing(); 
customConfirm("some importart question", function(result){ 
    doSomeThingElse(result); 
}); 

donde customConfirm ahora toma una pregunta y pasa el resultado a la función que toma como argumento. Si implementa un diálogo DOM con un botón, conecte un detector de eventos a los botones Aceptar y CANCELAR, y llame a la función de devolución de llamada cuando el usuario haga clic en uno de ellos.

+1

El ");" falta al final de tu código. – Frunsi

1

No creo que haya ninguna manera de volver a crear razonablemente la funcionalidad de confirm() o prompt() en su propio JavaScript.Son "especiales" en el sentido de implementarse como llamadas a la biblioteca del navegador nativo. Realmente no se puede hacer un diálogo modal de ese tipo en JavaScript.

He visto varias bibliotecas de IU que simulan el efecto al poner un elemento en la parte superior de la página, que parece & funciona como un diálogo modal, pero esas se implementan utilizando devoluciones de llamada asíncronas.

Deberá modificar la biblioteca existente, en lugar de reemplazar window.confirm.

7

O usa devoluciones de llamada o crea tu código solo para Firefox. En Firefox con soporte para JavaScript 1.7 y versiones posteriores, puede usar la declaración de rendimiento para simular el efecto deseado. Creé una biblioteca para este propósito llamada async.js. La biblioteca estándar para async.js incluye un método de confirmación, que puede ser utilizado como tal:

if (yield to.confirm("...")) { 
    // user pressed OK 
} else { 
    // user pressed Cancel 
} 
0

He intentado utilizar un bucle apretado para this. Necesitaba ralentizar un evento nativo (que AFAIK es el único caso de uso para una espera síncrona que no puede rediseñarse de forma asíncrona). Hay muchos bucles de ejemplo que afirman no bloquear el navegador; pero ninguno de ellos funcionó para mí (el navegador no se bloqueó, pero impidieron que hiciera lo que estaba esperando en primer lugar), así que abandoné la idea.

Luego probé this - almacenando y reproduciendo el evento, que parece ser imposible también entre navegadores. Sin embargo, dependiendo del evento y de la flexibilidad que necesite tener, puede acercarse.

Al final me rendí y me sentí mucho mejor por ello; Encontré una manera de hacer que mi código funcionara sin tener que ralentizar el evento nativo en absoluto.

3

Hay una extensión del lenguaje JavaScript llamada StratifiedJS. Se ejecuta en todos los navegadores y le permite hacer exactamente eso: detener una línea de código JavaScript sin congelar el navegador.

Puede habilitar JavaScript estratificado p. Ej. mediante la inclusión de Oni Apolo (http://onilabs.com/docs) en su página web como:

<script src="http://code.onilabs.com/latest/oni-apollo.js"></script> 
<script type="text/sjs"> your StratifiedJS code here </script> 

Su código se vería así:

var dom = require("dom"); 
displayYourHtmlDialog(); 
waitfor { 
    dom.waitforEvent("okbutton", "click"); 
    // do something when the user pressed OK 
} 
or { 
    dom.waitforEvent("cancelbutton", "click"); 
} 
hideYourHtmlDialog(); 
// go on with your application 
Cuestiones relacionadas