Quiero entender el funcionamiento interno de node.js, incluyo intencionalmente la tarea de cálculo (bucle for). Pero veo que todavía está bloqueando el hilo principal.
Aquí está mi guión
console.log("start"); for (let i = 0; i < 10; i++) { console.log(i) } console.log("end")Y el o/p es: inicio
1
2
3
....
10
final
Pero de acuerdo con la arquitectura node.js, ¿no deberían ejecutarse tareas de alto cálculo mediante diferentes subprocesos seleccionados del grupo de subprocesos y el ciclo de eventos continúa ejecutando tareas sin bloqueo? 
Estoy haciendo referencia a la arquitectura interna de node.js usando este enlace ingrese la descripción del enlace aquí
¿Alguien puede explicar la arquitectura y el comportamiento del script?
De forma predeterminada, nodejs usa solo UN hilo para ejecutar su Javascript. Eso significa que (a menos que utilice WorkerThreads, que son esencialmente una VM completamente separada), solo se ejecuta una pieza de Javascript a la vez. Nodejs no "detecta" alguna pieza de Javascript de ejecución prolongada y la mueve a otro hilo. No tiene características como esa en absoluto. Si tiene una pieza de Javascript síncrono de ejecución prolongada, bloqueará el bucle de eventos y bloqueará todos los demás Javascript y todos los demás procesos de eventos.
Interno a su implementación, nodejs tiene un grupo de subprocesos que utiliza para ciertos tipos de código nativo (implementaciones internas de E/S de archivos y operaciones criptográficas). Eso solo admite la implementación de implementaciones asincrónicas para la E/S de archivos y las operaciones criptográficas; no paraleliza la ejecución de Javascript.
Entonces, tu script que muestras:
console.log("start"); for (let i = 0; i < 10; i++) { console.log(i) } console.log("end")Es completamente síncrono y se ejecuta secuencialmente y bloquea la ejecución de todos los demás Javascript mientras se ejecuta porque está utilizando un hilo para ejecutar Javascript mientras se ejecuta.
Nodejs obtiene su excelente escalabilidad de su modelo de E/S asíncrono que no tiene que usar un subproceso separado para tener muchas operaciones asíncronas en vuelo al mismo tiempo. Pero tenga en cuenta que todas estas operaciones de E/S asíncronas tienen código nativo detrás de ellas (algunas de las cuales pueden usar subprocesos en sus implementaciones de código nativo).
Pero, si tiene operaciones Javascript sincrónicas de ejecución prolongada (como, por ejemplo, un análisis de imágenes escrito en Javascript), entonces, por lo general, es necesario sacarlas del subproceso del bucle de eventos principal desviándolas a WorkerThreads o a otros procesos o a un implementación de código nativo que puede usar subprocesos del sistema operativo.
Pero de acuerdo con la arquitectura node.js, ¿no deberían ejecutarse tareas de alto cálculo mediante diferentes subprocesos seleccionados del grupo de subprocesos y el ciclo de eventos continúa ejecutando tareas sin bloqueo?
No, no es así como funciona nodejs y no es una interpretación correcta del diagrama que muestra. El grupo de subprocesos NO se utiliza para ejecutar su Javascript. Se utiliza para la implementación interna de algunas API, como la E/S de archivos y algunas operaciones criptográficas. No se utiliza para ejecutar su Javascript. Solo hay un hilo principal para ejecutar su Javascript (a menos que ejecute específicamente su código en un WorkerThread).
Quiero entender el funcionamiento interno de node.js, incluyo intencionalmente la tarea de cálculo (bucle for). Pero veo que todavía está bloqueando el hilo principal.
Sí, un bucle for (que no contiene una declaración de await que está esperando una promesa) ocupará por completo el único subproceso de Javascript y bloqueará el bucle de eventos para que no procese otros eventos mientras se ejecuta el bucle for .
No hay absolutamente ningún subproceso en JS (a menos que utilice explícitamente subprocesos de trabajo). Javascript utiliza la multitarea cooperativa, lo que significa que una función siempre se completará antes de que comience la siguiente. La única otra forma de devolver el control al programador es separar una tarea en otra función que se llama de forma asíncrona. Entonces, en tu ejemplo, por ejemplo, podrías hacer:
console.log("start"); setTimeout(() => { for (let i = 0; i < 10; i++) { console.log(i) }}, 0); console.log("end")y obtendrías:
start end 1 2 .. 9Esto también responde a su pregunta sobre cálculos pesados: a menos que use subprocesos de trabajo relativamente nuevos, no puede ejecutar cálculos pesados en node.js "en segundo plano" sin el uso de código nativo.
Entonces, si realmente tiene cargas pesadas, tiene tres opciones:
JS ejecuta su código Synchronouse. hay algunas cosas que se vuelven "Asynchronouse" como setInterval o setTimout por ejemplo. Pero eso en realidad no es del todo cierto. Asíncrono significa que las cosas se hacen en paralelo, lo que no es cierto. Echa un vistazo a setTimeout . Al ejecutarlo, agrega la función a la cola de tareas, luego el bucle de eventos la toma de la cola, la coloca en la pila y la ejecuta, de forma sincronizada. Si desea ejecutar algo realmente paralelo, debería considerar usar un subproceso de trabajo