Hilo único de JavaScript
El enhebrado único de JavaScript está relacionado con su propósito. Como lenguaje de guiones de navegador, el objetivo principal de JavaScript es interactuar con los usuarios y operar DOM. Esto determina que solo puede ser un solo enhebrado, de lo contrario causará problemas de sincronización muy complejos. Por ejemplo, suponga que JavaScript tiene dos hilos al mismo tiempo, un hilo agrega contenido en un determinado nodo DOM, y el otro hilo elimina este nodo, ¿qué hilo debería tomar el navegador en este momento? Por lo tanto, para evitar la complejidad, JavaScript es un solo hilo de su nacimiento, que se ha convertido en la característica central de este idioma y no cambiará en el futuro.
Tareas de cola
El enhebrado único significa que todas las tareas deben colocarse en cola, y la tarea anterior se ejecutará antes de que se ejecute la próxima tarea. Si la tarea anterior lleva mucho tiempo, la siguiente tarea tiene que esperar.
Controlador de eventos asíncronos
Muchos comportamientos en el navegador están asincronizados, como: evento de clic del mouse, evento de arrastre de tamaño de ventana, evento de activación del temporizador, devolución de llamada de finalización XMLHTTPREQUEST, etc. Cuando se produce un evento asíncrono, ingresa a la cola de eventos. El navegador tiene un bucle de mensajes grande interno, bucle de eventos, que encuestará grandes colas de eventos y procesará eventos. Por ejemplo, el navegador está actualmente ocupado procesando el evento OnClick, y luego ocurre otro evento (como Window Onsize), y este evento asíncrono se pone en la cola de eventos y espera el procesamiento. Este evento se ejecutará solo cuando se complete el procesamiento anterior y sea gratuito.
Bucle de eventos
JavaScript es de un solo hilo, pero el navegador no es un solo subproceso
El navegador tendrá al menos algunos de los siguientes procesos.
1. Hilo de representación de GUI del navegador
2. Hilo del motor JavaScript
3. Hilo de gatillo cronometrado del navegador
4. Evento del navegador desencadena el hilo
5. HTTP HTTP HTTTP HILO
Debido a que el motor JavaScript está de un solo hilo, el código primero se presiona a la cola y luego se ejecuta por el motor de una manera en primer lugar. Las funciones de manejo de eventos y las funciones de ejecución del temporizador también se colocarán en esta cola, y luego usará un bucle infinito para extraer continuamente las funciones del jefe del equipo para ejecutar. Este es el bucle de eventos.
En resumen, JS es de un solo hilo, pero el navegador es multiproceso. Al encontrar cosas asíncronas, el navegador colocará la devolución de llamada asíncrona en el bucle de eventos. Cuando el hilo JS no esté ocupado, lea el bucle del evento.
Principio del temporizador
Cómo usar el temporizador
setTimeOut (fn, retraso)
setInterval (fn, retraso)
FN es una función o una cadena, el retraso es el momento del retraso, la unidad es milisegundos
Hay las siguientes cosas a tener en cuenta
1. Aunque FN puede ser una cadena, nunca se recomienda usarla así.
2. Si hay esta función en FN, esto apuntará a la ventana al ejecutar.
Si comprende bien el hilo único y el bucle de eventos, el principio del temporizador será fácil de entender.
Si se establece un temporizador, cuando se alcanza el tiempo de retraso, el navegador colocará el evento de ejecución retrasado en el bucle de eventos. Cuando se acelere el tiempo, si el hilo JS está inactivo, se ejecutará (por lo que la precisión del temporizador es inexacta)
Leí un artículo sobre la diferencia entre SetTimeout y SetInterval que siempre funciona las funciones. El código es el siguiente
La copia del código es la siguiente:
setTimeOut (function () {
SetTimeOut (Arguments.Callee, 100)
}, 100)
setInterval (function () {}, 1000)
El significado general del artículo es que SetTimeout inicia el siguiente temporizador después de ejecutar la función de devolución de llamada, por lo que debe ejecutarse a intervalos, mientras que SetInterval se ejecuta todo el tiempo. Si encuentra un hilo JS que sigue ejecutando, puede agregar varias devoluciones de llamada en el bucle de eventos. Cuando el hilo JS no está ocupado, se ejecutarán múltiples ejecuciones una tras otra.
Después de la prueba, se descubrió que SetInterval está en un cierto intervalo, sin importar IE, FF, Chrome, Opera y Safari.
El código de prueba es el siguiente
La copia del código es la siguiente:
setInterval (function () {
xx.innerhtml = xx.innerhtml+1;
}, 100);
para (var i = 0; i <6000000; i ++) {
xx.OffsetWidth
}
setTimeOut (function () {
depurador;
}, 10)
Cuando los puntos de interrupción todavía se imprimen solo 1
Problemas de precisión del temporizador
Debido al hilo único JS, si te encuentras con el ajetreo, el temporizador definitivamente será inexacto, y definitivamente será más y más largo. Esto parece ser insoluble, sin solución.
Otro problema de precisión es el intervalo mínimo setTimeOut (diversión, 0)
Cuando el hilo JS no está ocupado, es imposible ejecutar inmediatamente después de 0 segundos. Siempre hay un intervalo mínimo, y cada navegador sigue siendo diferente. Esto no ha sido probado.
Leí un artículo sobre el estándar de W3C. La ejecución mínima del tiempo del temporizador es de 4 ms. ¡No hay forma de verificar la fuente si no puede encontrarla! ! !
Algunas optimizaciones relacionadas con los temporizadores
Todavía hay algunas optimizaciones al hacer temporizadores
1. Por ejemplo, si ata la ventana. Cuando se borra la próxima ejecución, reducirá la ejecución frecuente.
El pseudo-código es el siguiente
La copia del código es la siguiente:
temporizador var;
función r () {
ClearTimeOut (temporizador);
timer = setTimeOut (function () {
// Haz algo
}, 150);
}
2. Cuando se tira la barra de desplazamiento hacia abajo, también es un poco. Por ejemplo, la carga de la imagen también debe tener un temporizador para evitar cálculos excesivos.
3. Cuando hay varios lugares donde se necesitan temporizadores, puede fusionarlos en un temporizador. El intervalo de tiempo es el más pequeño. Luego, la función de devolución de llamada que debe ejecutarse se rellena en la matriz. Cuando se alcanza el intervalo de tiempo, itera a través de la matriz para ejecutar.
Una pequeña demostración
La copia del código es la siguiente:
<! Doctype html>
<html>
<Evista>
<meta charset = "utf-8" />
<estilo>
.wrap {ancho: 80%; Margen: 30px Auto; borde: 1px sólido #ccc; relleno: 20px;}
.c {border: 1px sólido #ccc; Altura: 30px; margen-bottom: 20px;}
</style>
</ablo>
<Body>
<div id = "xx"> </div>
<div>
<div id = "a1"> 0 </div>
<div id = "a2"> 0 </div>
<div id = "a3"> 0 </div>
<div id = "a4"> 0 </div>
</div>
<script src = "http://static.paipaiimg.com/paipai_h5/js/ttj/zepto.min.js"> </script>
<script type = "text/javaScript">
var tiempo de ejecución = {
Opciones: {
Paso: 1000
},
devoluciones de llamada: [],
addCallbacks: [],
Inicio: falso,
Temporizador: NULL,
extender: function () {
var objetivo = argumentos [0] || {}, i = 1, longitud = argumentos.length, opciones;
if (typeof Target! = "Object" && typeof Target! = "Función")
objetivo = {};
para (; i <longitud; i ++)
if ((opciones = argumentos [i])! = nulo)
para (nombre var en opciones) {
var copy = options [nombre];
if (Target === Copy)
continuar;
if (Copy! == Undefined)
objetivo [nombre] = copia;
}
objetivo de retorno;
},
init: function (opciones) {
$ .extend (this, this.options, opciones || {});
},
Agregar: función (diversión, opciones) {
opciones = opciones || {};
this.addcallbacks.push ({
Diversión: diversión,
Starttime: New Date (). GetTime (),
Paso: Opciones.step || this.step,
I: 1
});
var self = this;
if (! this.start) {
this.callbacks = [diversión];
this.Start = True;
this.starttime = new Date (). GetTime ();
this.timer = setInterval (function () {
self.done ();
}, this.step);
}
},
hecho: function () {
VAR Callbacks = this.Callbacks,
Self = esto,
newarr = [];
$ .each (devoluciones de llamada, función (i, obj) {
if (obj.step == self.step) {
obj.fun ();
}demás{
if (obj.i == obj.step/self.step) {
if ((nueva fecha (). getTime ())-obj.starttime> obj.step*2/3) {
obj.fun ();
}
obj.i = 1;
}demás{
obj.i = obj.i + 1;
}
}
});
$ .each (this.addcallbacks, function (i, obj) {
if (obj.step == self.step) {
if ((nueva fecha (). getTime ())-obj.starttime> obj.step*2/3) {
obj.fun ();
callbacks.push (obj);
}demás{
newarr.push (obj);
}
}demás{
obj.i = obj.i + 1;
callbacks.push (obj);
}
});
this.addCallbacks = newarr;
},
claro: function () {
ClearInterval (this.timer);
}
}
runtime.init ();
runtime.add (function () {
a1.innerhtml = ~~ a1.innerhtml+1;
});
runtime.add (function () {
a2.innerhtml = ~~ a2.innerhtml+1;
}, {paso: 2000});
runtime.add (function () {
a3.innerhtml = ~~ a3.innerhtml+1;
}, {paso: 4000});
runtime.add (function () {
a4.innerhtml = ~~ a4.innerhtml+1;
}, {paso: 8000});
</script>
</body>
</html>
¿Tienes alguna idea sobre el temporizador de JavaScript? Déjame un mensaje si tienes alguna pregunta.