JavaScript es un lenguaje de un solo subproceso, llamado un solo subproceso, sincrónico o asincrónico

JavaScriptEs un lenguaje de subproceso único, el llamado subproceso único

 

Js mecanismo asincrónico

JavaScriptEs un lenguaje de subproceso único. El llamado subproceso único significa que solo se puede completar una tarea a la vez. Si hay varias tareas, se debe poner en cola. La tarea anterior se completa y luego se ejecuta la última tarea, y así sucesivamente. La ventaja de este modo es que es relativamente simple de implementar, y el entorno de ejecución es relativamente simple. La desventaja es que, mientras haya una tarea que lleve mucho tiempo, las tareas posteriores deben ponerse en cola y retrasarán la ejecución de todo el programa. Los navegadores comunes no responden, lo cual es un estado de falsa muerte, a menudo porque un determinado fragmento de Javascriptcódigo se ejecuta durante mucho tiempo, como un bucle infinito, lo que hace que toda la página se atasque en este lugar y no se puedan ejecutar otras tareas.

Mecanismo de ejecución #

Para resolver los problemas anteriores, Javascriptel modo de ejecución de la tarea se divide en dos tipos: sincrónico Synchronousy asincrónico Asynchronous, sincrónico o asincrónico, lo que indica si todo el proceso debe completarse en secuencia, bloqueando o no bloqueando, lo que significa que la función que llama no Decirle el resultado de inmediato.

Sincronización #

El modo sincrónico es el bloqueo sincrónico. La última tarea espera el final de la tarea anterior y luego la ejecuta. El orden de ejecución del programa es coherente con el orden de las tareas.

Copiar
var i = 100;
while(--i) { console.log(i); }
console.log("while 执行完毕我才能执行"); 

# Asincrónico

La ejecución asincrónica es la ejecución en modo sin bloqueo. Cada tarea tiene una o más funciones de devolución de llamada callback. Después de que finaliza la tarea anterior, en lugar de ejecutar la siguiente tarea, se ejecuta la función de devolución de llamada. Esta última tarea se ejecuta sin esperar el final de la tarea anterior. Por lo tanto, el orden de ejecución del programa y el orden de las tareas son inconsistentes y asíncronos. El navegador Tabsolo asigna un Jshilo para cada uno , la tarea principal es interactuar con el usuario y operar, DOMetc., lo que determina que solo puede ser un solo hilo, de lo contrario traerá problemas de sincronización muy complicados, por ejemplo, suponga que JavaScripthay dos hilos , Un subproceso DOMagrega contenido en un determinado nodo, otro subproceso elimina el nodo y el navegador no puede determinar qué operación prevalecerá.

Copiar
setTimeout(() => console.log("我后执行"), 0); // 注意:W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms,此外这与浏览器设定、主线程以及任务队列也有关系,执行时间可能大于4ms,例如老版本的浏览器都将最短间隔设为10毫秒。另外,对于那些DOM的变动尤其是涉及页面重新渲染的部分,通常不会立即执行,而是每16毫秒执行一次。这时使用requestAnimationFrame()的效果要好于setTimeout()。 console.log("我先执行"); 

Mecanismo asincrónico #

Primero veamos un ejemplo, para probar una operación ejecutada asincrónicamente como se indica arriba

Copiar
setTimeout(() => console.log("我在很长时间之后才执行"), 0); var i = 3000000000; while(--i) { } console.log("循环执行完毕"); 

Pruebas locales, el conjunto de setTimeoutfunciones de devolución de llamada 30sse ejecuta después de aproximadamente , que es mucho mayor que 4mseso. Configuré un bucle muy grande en el Jshilo principal para bloquear el hilo principal. Tenga en cuenta que no configuré un bucle infinito. Si configuro aquí un bucle infinito Para bloquear el subproceso principal, la setTimeoutfunción de devolución de llamada nunca se ejecutará. Además, debido a que el subproceso de representación y el subproceso del JSmotor son mutuamente exclusivos, el Jssubproceso de representación se suspenderá mientras el subproceso está procesando la tarea, toda la página se bloqueará y no se puede actualizar o incluso No se puede cerrar, y la página solo se puede cerrar utilizando el administrador de tareas para finalizar el Tabproceso.
JsAsíncrono se logra a través de una pila de ejecución y una cola de tareas para completar operaciones asíncronas. Todas las tareas síncronas se ejecutan en el hilo principal para formar una pila de ejecución. Varias devoluciones de eventos (también llamados mensajes) se almacenan en la cola de tareas. Una vez que se completa el procesamiento de la tarea en la pila de ejecución, el subproceso principal comienza a leer las tareas en la cola de tareas y las ejecuta, correspondiendo continuamente al bucle.
Por ejemplo, la setTimeoutdevolución de llamada de evento completada en el ejemplo anterior se almacena en la cola de tareas. Debe tenerse en cuenta que el JavaScriptmotor no cuenta el contador del temporizador del navegador , porque el JavaScriptmotor tiene un solo subproceso. Si el subproceso está bloqueado, afectará el tiempo. Precisamente, el recuento se cuenta por el subproceso del navegador. Cuando se completa el recuento, la devolución de llamada del evento se agrega a la cola de tareas. Del mismo modo HTTP, hay un subproceso separado en el navegador, y la devolución de llamada del evento se coloca en la cola de tareas después de la ejecución. A través de este proceso, podemos explicar por qué setTimeoutla devolución de llamada en el ejemplo anterior no se pudo ejecutar, porque el hilo principal, es decir, el código en la pila de ejecución no se ha completado, no leerá la devolución de llamada del evento en la cola de tareas para ejecutar, incluso si esta devolución de llamada de evento ya se ha ejecutado. En la cola de tareas.

Evento Loop #

El hilo principal se lee de la cola de tareas caso, el proceso se circula constantemente, por lo que también se conoce toda la operación de este mecanismo Event Loop, Event Loopes un modelo ejecutivo, implementado de manera diferente en diferentes lugares, navegador y NodeJSimplemento basados en diferentes tecnologías su propio Event Loop. El navegador está claramente definido Event Loopen HTML5la especificación NodeJSy Event Loopse basa en la libuvimplementación.
Se Event Loopcompone de pila de ejecución Execution Stack, subproceso de fondo Background Threads, macro cola Macrotask Queuey micro cola en el navegador Microtask Queue.

  • La pila de ejecución es una estructura de datos que ejecuta tareas de sincronización en el subproceso principal. La llamada a la función forma una pila que consta de varias tramas.
  • Lograr subproceso en segundo plano es el navegador para setTimeout, setInterval, XMLHttpRequesty así sucesivamente hilo de ejecución.
  • cola de macro, algunas de las tareas asíncronas se convertirá en la cola de devolución de llamada macro, a la espera de ser llamado de seguimiento, incluyendo setTimeout, setInterval, setImmediate(Node), requestAnimationFrame, UI rendering, I/Oy otras operaciones
  • Microqueue, otras tareas asíncronas se convertirá en la cola de micro devolución de llamada, a la espera de las llamadas de seguimiento, incluyendo Promise, process.nextTick(Node), Object.observe, MutationObservery otras operaciones

Cuando se Jsejecute, proceda de la siguiente manera

  1. Primero, el código en la pila de ejecución se ejecuta sincrónicamente, y las tareas asincrónicas en estos códigos se agregan al hilo de fondo
  2. Después de ejecutar el código de sincronización en la pila de ejecución, la pila de ejecución se vacía y se escanea la microcola
  3. Tome la primera tarea de la micro cola y colóquela en la pila de ejecución para su ejecución. En este momento, la micro cola está en cola
  4. Cuando se complete la pila de ejecución, continúe eliminando y ejecutando las tareas de micro cola hasta que todas las tareas de micro cola estén ejecutadas
  5. Después de que la última tarea de microcola se elimine y entre en la pila de ejecución, la tarea en la micro cola estará vacía. Cuando se complete la tarea de la pila de ejecución, la micro cola comenzará a escanear la superficie. Continúe escaneando la tarea de macro cola. Ejecución en el medio, una vez completada la ejecución, continúe escaneando la micro cola que está vacía, luego escanee la macro cola, elimine la ejecución
  6. Sigue yendo y viniendo ...

Ejemplo #

Copiar
// Step 1
console.log(1);

// Step 2
setTimeout(() => { console.log(2); Promise.resolve().then(() => { console.log(3); }); }, 0); // Step 3 new Promise((resolve, reject) => { console.log(4); resolve(); }).then(() => { console.log(5); }) // Step 4 setTimeout(() => { console.log(6); }, 0); // Step 5 console.log(7); // Step N // ... // Result /* 1 4 7 5 2 3 6 */ 
Paso 1
Copiar
// 执行栈 console
// 微队列 []
// 宏队列 []
console.log(1); // 1 
Paso 2
Copiar
// 执行栈 setTimeout
// 微队列 []
// 宏队列 [setTimeout1]
setTimeout(() => { console.log(2); Promise.resolve().then(() => { console.log(3); }); }, 0); 
Paso 3
Copiar
// 执行栈 Promise
// 微队列 [then1]
// 宏队列 [setTimeout1]
new Promise((resolve, reject) => { console.log(4); // 4 // Promise是个函数对象,此处是同步执行的 // 执行栈 Promise console resolve(); }).then(() => { console.log(5); }) 
Paso 4
Copiar
// 执行栈 setTimeout
// 微队列 [then1]
// 宏队列 [setTimeout1 setTimeout2]
setTimeout(() => { console.log(6); }, 0); 
Paso 5
Copiar
// 执行栈 console
// 微队列 [then1]
// 宏队列 [setTimeout1 setTimeout2]
console.log(7); // 7 
Paso 6
Copiar
// 执行栈 then1
// 微队列 []
// 宏队列 [setTimeout1 setTimeout2]
console.log(5); // 5 
Paso 7
Copiar
// 执行栈 setTimeout1
// 微队列 [then2]
// 宏队列 [setTimeout2]
console.log(2); // 2 Promise.resolve().then(() => { console.log(3); }); 
Paso 8
Copiar
// 执行栈 then2
// 微队列 []
// 宏队列 [setTimeout2]
console.log(3); // 3 
Paso 9
Copiar
// 执行栈 setTimeout2
// 微队列 []
// 宏队列 []
console.log(6); // 6 

Referencia #

Copiar
https://www.jianshu.com/p/1a35857c78e5
https://segmentfault.com/a/1190000016278115
https://segmentfault.com/a/1190000012925872 https://www.cnblogs.com/sunidol/p/11301808.html http://www.ruanyifeng.com/blog/2014/10/event-loop.html https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/EventLoop

Supongo que te gusta

Origin www.cnblogs.com/Leo_wl/p/12737282.html
Recomendado
Clasificación