function main() { console.log("S-1"); setTimeout(() => { console.log("setTimeout"); }, 0); new Promise((resolve, reject) => { for (let i = 0; i < 10000000000; i++) {} resolve("Promise"); }).then((res) => console.log(res)); console.log("S-2"); } // Invoke function main();Cuando ejecuto la función main(), el resultado que obtengo es:
'S-1' 'S-2' 'Promise' 'setTimeout'Después de que se registra 'S-1', hay una gran brecha de tiempo, y luego de unos segundos, el resto se registra, a la vez. ¿No debería ocurrir el intervalo de tiempo después de registrar 'S-2'?
La función dentro del constructor Promise se ejecuta sincrónicamente, en el mismo (y único) subproceso principal que el resto del script. Construir una Promesa no da como resultado la creación de un hilo separado.
Si realiza un procesamiento pesado inmediatamente dentro de un constructor de Promise, ese procesamiento pesado deberá completarse antes de que el flujo de control se devuelva al exterior del constructor de Promise. En este caso, significa que las muchas iteraciones del ciclo deben terminar antes de:
.then adjuntoconsole.log("S-2"); carreras de líneaPara obtener el resultado que desea o espera sin mover los registros, debe descargar el código costoso en un entorno diferente, como un trabajador o un servidor (mediante una solicitud de red).
Como dijo @CertainPerformance, Javascript solo puede manejar una pila de llamadas. Tiene que terminar este hilo de una vez por todas. Para promesas y tiempos de espera, utiliza las colas de trabajos y tareas. El bucle de eventos prioriza la cola de trabajos y luego la cola de tareas.
Tratemos de entender lo que escribió en términos de pila de llamadas y colas.
function main() { // 1. execute straight forward console.log("S-1"); // 2. sets / schedules a timer, the anonymous function is then stored in the callback setTimeout(() => { console.log("setTimeout"); }, 0); // 3. create a new Promise, with the constructor acting as executor // executes immediately, as its designed to set the state of the Promise for the then() to react to. new Promise((resolve, reject) => { for (let i = 0; i < 10000000000; i++) {} // 3.5 the resolve signals that the execution is finished // either returns the promise or passes through the then() resolve("Promise"); // 4. after the promise execution has been resolved, // then() creates another anonymous function, and stores in the callback. // at this point there are 2 entries in the callback }).then((res) => console.log(res)); // 5. once the above Promise executor has been executed, execute this console.log("S-2"); // By now, since both the timer and promise execution has been done, // the timeout is put into the Task Queue and the Promise then() is put into the Job Queue. } // 0. puts this into the call stack and execute main(); // 6. The event loop deques all of the call stack from the job queue and puts it into the main call stack to execute. // hence, the then() is executed first // 7. The event loop then deques all of the call stack from the task queue and puts it into the main call stack to execute. // hence, the timeout function is executed next.Si desea que sea una devolución de llamada.
function main() { console.log("S-1"); setTimeout(() => { console.log("setTimeout"); }, 0); new Promise((resolve, reject) => { setTimeout(() => { resolve("promise"); }, 1000); }).then((res) => console.log(res)); console.log("S-2"); } // Invoke function main();Referencia: https://medium.com/@idineshgarg/let-us-consider-an-example-a58bb1c11f55