Estoy leyendo MDN sobre cómo funciona el código asíncrono con javascript. Proponen este ejemplo:
async function myFetch() { let response = await fetch('coffee.jpg'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } let myBlob = await response.blob(); let objectURL = URL.createObjectURL(myBlob); let image = document.createElement('img'); image.src = objectURL; document.body.appendChild(image); } myFetch() .catch(e => { console.log('There has been a problem with your fetch operation: ' + e.message); });
Se define la función myFetch() y luego se llama en un estilo Promise-way. ¿Cómo se ejecuta exactamente la función? Es una función asíncrona, así que supongo que se le da a algún subproceso para ejecutar sin interferir con el único subproceso que ejecuta el código Javascript. También en los documentos dijeron que esperar está deteniendo el código en esa línea hasta que se complete. Entonces, ¿la función no puede ser ejecutada por el hilo principal de la aplicación porque ya no es un código asíncrono? Esos son mis problemas y quiero estar seguro de que entiendo este mecanismo antes de comenzar a escribir el código real. ¡Gracias!
usar async/await es bastante similar a usar promesas, la función asíncrona devuelve una Promesa para usted, esa promesa puede tener uno de los tres estados (Pendiente, Cumplida, Rechazada)
De forma predeterminada, la promesa devuelta se cumple (resuelve) de forma similar a:
Promise.resolve().then(_ => { //... })
usando await, la Promesa estará pendiente en el código que está esperando
new Promise((resolve, reject) => { // ... some tasks here resolve(resolvedData); }) .then(_ => { //... })
cuando se lanza un error, automática o manualmente, la Promesa será rechazada
new Promise((resolve, reject) => { reject(); // Reject manually }) .then(_ => { }) .catch(e => { //... })
De forma predeterminada, todo el código de JavaScript se ejecuta dentro del hilo principal, que es el único hilo que tiene JavaScript.
Mira el siguiente ejemplo:
async function c() { const t = await Array.from(Array(100000000).keys()) } c().then(t => console.log('I am waiting for the Promise to be fulfilled!')) console.log('Hey, I don\'t need to wait');
Obtendrá el resultado esperado:
"Hey, I don't need to wait" "I am waiting for the Promise to be fulfilled!"
pero ambos registros están esperando para llenar esta matriz 100000000
, por lo que el hilo principal ahora está ocupado y bloqueado para completar esta tarea primero, JavaScript en sí no puede ayudar con este caso,
Otro ejemplo:
async function c() { const t = await fetch('https://jsonplaceholder.typicode.com/photos') } c().then(_ => console.log('I am waiting for the Promise to be fulfilled!')) console.log('Hey, I don\'t need to wait');
Aquí obtendrá el mismo resultado, pero Hey, I don't need to wait
, se registrará de inmediato, ¡y solo I am waiting for the Promise to be fulfilled!
Estare esperando,
¿Por qué? aquí necesitamos referirnos a algunas cosas importantes para leer más (bucle de eventos, pila de llamadas, tareas micro y macro)
En palabras simples, la promesa se comporta igual, está pendiente de algo, y el primer inicio de sesión de la consola en el código está esperando que se cumpla la promesa,
la diferencia es que la tarea que estamos esperando para tener una promesa cumplida ahora no es el bloqueo de subprocesos, no está controlado por JavaScript en sí
la tarea de recuperación es administrada por una API externa que es observada por el bucle de eventos, en este caso, la pila de llamadas no estará ocupada y el subproceso principal de JavaScript puede seguir funcionando, el código que resolverá la promesa se agrega a una cola y será enviado a la pila de llamadas por el bucle de eventos cuando la API externa realice la tarea de obtención
Se define la función myFetch() y luego se llama en un estilo Promise-way.
Se llama como cualquier otra función. Todas las funciones async
envuelven el valor de retorno en una Promesa, por lo que hay métodos disponibles then
, catch
y finally
.
¿Cómo se ejecuta exactamente la función?
Usando ()
como cualquier otra función.
Es una función asíncrona, así que supongo que se le da a algún subproceso para ejecutar sin interferir con el único subproceso que ejecuta el código Javascript.
No es necesario que se ejecute en otro subproceso. Como dices, la ejecución de JavaScript ocurre en un solo hilo.
También en los documentos dijeron que esperar está deteniendo el código en esa línea hasta que se complete.
Sí, en esa función asíncrona.
Entonces, ¿la función no puede ser ejecutada por el hilo principal de la aplicación porque ya no es un código asíncrono?
No tiene que haber ningún subprocesamiento involucrado. Solo las operaciones de fetch
y blob
se realizan de forma asincrónica. Mientras se esperan esas operaciones, el bucle de eventos y la ejecución de código fuera de la función asíncrona continuarán. Si tiene un código debajo de la llamada a myFetch
, se ejecutará mientras se espera la fetch
, a menos que espere la llamada a myFetch
.
async
y await
son azúcar sintáctico además de Promises, por lo que efectivamente su código está haciendo lo siguiente:
fetch('coffee.jpg').then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } response.blob().then(myBlob => { let objectURL = URL.createObjectURL(myBlob); let image = document.createElement('img'); image.src = objectURL; document.body.appendChild(image); }); }).catch(e => { console.log('There has been a problem with your fetch operation: ' + e.message); });