retrasar - ¿Se puede interrumpir el flujo de ejecución de JavaScript?
problemas de eyaculación precoz (2)
Siempre he pensado que, dado que JavaScript era de un solo hilo, podía adjuntar controladores de eventos sin preocuparme de que los controladores se ejecutaran mientras estaba en medio de ejecutar el código. Para mi sorpresa, encontré que podían. De acuerdo con esta respuesta, el cuadro de diálogo ''Secuencia de comandos que no responde'' puede provocar que se generen eventos mientras la secuencia de comandos aún se está ejecutando.
He probado esto con el siguiente código:
<script>
function loop() {
var cond;
onblur = function (event) {
cond = false;
};
cond = true;
while (cond)
;
alert(''loop exited!'');
}
</script>
<button onclick="loop()">loop()</button>
En Firefox 11.0, la función imprime "bucle salido" después de hacer clic en continuar. El bucle parece estar en pausa, con eventos permitidos para ejecutarse. Esto es similar a una señal de Unix, que cambia temporalmente el contexto del hilo objetivo. Pero es mucho más peligroso, ya que permite alterar el estado externo.
¿Es esto un error? ¿Debo dejar de depender del modelo de JavaScript de flujo de ejecución único y asegurarme de que todos mis scripts son reingresados? ¿O es una falla que no vale la pena perseguir a pesar de que un navegador importante permite que esto suceda?
Así que sí, si creas un bucle infinito colgarás tu JavaScript. Los navegadores diferenciales manejarán esto de manera diferente. Firefox 11 para mí me abre una ventana diciendo que tu script se ha colgado. Chrome está girando para mí en este momento.
Esto debería probar el punto. Nunca llama alert()
en FF11 o Chrome 17.
while(true){}
alert("sucks");
Usted preguntó acerca de las declaraciones de sincronización en JavaScript. Hay algunas otras declaraciones síncronas que bloquearán la ejecución de JavaScript como alert()
, confirm()
, llamadas ajax síncronas y más.
Por lo general, usted quiere evitar cualquier tipo de cosas sincrónicas en JavaScript! Si desea que las cosas se detengan, puede volver a pensar el diseño. JavaScript es impulsado por eventos . No lo necesita para girar en un bucle de tiempo, porque nada en la página funcionará, incluidos eventos como clics, etc.
Creo que el problema surge cuando empiezas a lidiar con los eventos.
En lugar de usar un bucle while, considere usar una función recursiva.
Aquí hay algunas modificaciones que hice en tu código que deberían ejecutarse según lo deseado.
<head>
<script>
function loop(that) {
var cond;
that.onblur = function (event) {
cond = false;
};
cond = true;
var loop = 0
var xy = function x (){
if(cond == true){
loop++;
setTimeout(function(){xy()},0);
} else {
alert(''loop exited! - ''+loop);
return true;
}
}
xy();
}
</script>
</head>
<body>
<button onclick="this.focus(); loop(this)">loop()</button>
</body>
El uso de setTimeout () con un retraso de 0 debe permitir que cualquier evento se active sin ningún problema. Su código de bucle no se ejecutará tan rápido, pero solo tendrá que probarlo y ver.