La naturaleza de subproceso único de JavaScript/Typescript: programación asíncrona

Jan 20 2023
En mi primer artículo escribí sobre algunas de las diferencias entre JS y TS. Ahora vamos a explorar la naturaleza asíncrona como un lenguaje de un solo subproceso.

En mi primer artículo escribí sobre algunas de las diferencias entre JS y TS.

Ahora vamos a explorar la naturaleza asíncrona como un lenguaje de un solo subproceso.

En JavaScript y TypeScript, la naturaleza de subproceso único significa que solo se puede ejecutar una tarea en un momento dado.

Por otro lado, la programación asíncrona se refiere a la capacidad del lenguaje para realizar tareas de forma asíncrona, lo que permite que el hilo principal de ejecución continúe ejecutándose mientras espera que se completen otras tareas. Esto se logra mediante el uso de devoluciones de llamada , eventos , promesas y async / await .

Antes de comenzar a explicar esto en términos de codificación, me gustaría hablar sobre una referencia muy interesante de cómo las tareas asincrónicas de un lenguaje de subproceso único son muy similares a nuestro cerebro cuando intentamos realizar múltiples tareas .

En esta sección resumiré un largo texto/capítulo escrito por Kyle Simpson en su libro “You Dont Know Javascript” sobre la conexión del Cerebro Secuencial con la asincronización. Si solo está interesado en la parte de codificación de cómo funciona, puede omitir esta parte.

“ Estoy bastante seguro de que la mayoría de ustedes ha escuchado a alguien decir (incluso usted mismo lo afirmó): “ Soy multitarea. ¿
Pero somos multitarea? ¿Podemos realmente hacer dos acciones conscientes e intencionales a la vez y pensar/razonar sobre ambas exactamente en el mismo momento? ¿Nuestro nivel más alto de funcionalidad cerebral tiene subprocesos múltiples paralelos?

La respuesta puede sorprenderte y es: probablemente no.

Simplemente no es así como nuestros cerebros parecen estar configurados. Somos mucho más autónomos de lo que a muchos de nosotros nos gustaría admitir. Realmente solo podemos pensar en una cosa en un instante dado.

No me refiero a todas nuestras funciones cerebrales involuntarias, subconscientes y automáticas, como los latidos del corazón, la respiración y el parpadeo de los párpados. Esas son todas tareas vitales para nuestra vida sostenida, pero no les asignamos intencionalmente ningún poder mental”.

Según Simpson, los humanos no son capaces de realizar múltiples tareas de la misma manera que una computadora. Si bien es cierto que el cerebro humano puede procesar múltiples tareas simultáneamente, no puede prestar la misma atención a todas las tareas a la vez. En cambio, cambiamos rápidamente nuestra atención entre tareas, al igual que un programa de un solo subproceso solo puede ejecutar una tarea a la vez.

Afortunadamente, mientras nos obsesionamos con revisar los feeds de las redes sociales por decimoquinta vez en tres minutos, nuestro cerebro continúa en segundo plano (¡subprocesos!) con todas esas tareas importantes.

Cuando simulamos realizar múltiples tareas, como tratar de escribir algo al mismo tiempo que estamos hablando con un amigo o familiar por teléfono, lo que en realidad estamos haciendo es actuar como cambiadores rápidos de contexto . En otras palabras, alternamos entre dos o más tareas en rápida sucesión, progresando simultáneamente en cada tarea en pequeños y rápidos fragmentos. Lo hacemos tan rápido que para el mundo exterior parece como si estuviéramos haciendo estas cosas en paralelo.

¿Te suena eso como simultaneidad de eventos asincrónicos (como lo que sucede en JS)?

Hay una gran diferencia observable entre cómo planeamos varias tareas y cómo nuestro cerebro realmente opera esas tareas.
Aunque a nivel operativo nuestros cerebros están sincronizados, parece que planificamos las tareas de forma secuencial y sincrónica. “Necesito ir a la tienda, luego comprar un poco de leche y luego dejar mi tintorería”.

¿Te imaginas tener una línea de pensamiento que planee tus tareas pendientes como esta:

“ Necesito ir a la tienda (1), pero en el camino estoy seguro de que me llamarán (2) , así que 'Hola, mamá', y mientras ella comienza a hablar, estaré mirando hacia arriba la dirección de la tienda (3) en el GPS, pero tardará un segundo en cargarse, así que bajaré el volumen de la radio (4) para poder escuchar mejor a mamá...
luego me daré cuenta de que olvidé ponerme una chaqueta ( 5) y hace frío afuera, pero no importa, sigue manejando y hablando con mamá…
y luego el sonido del cinturón me recuerda abrocharme el cinturón (6) , así que 'Sí, mamá, estoy usando el cinturón de seguridad, ¡siempre lo uso!'. Ah, finalmente:

el GPS obtuvo las direcciones, ahora…”

Tan ridículo como suena como una formulación de cómo planificamos nuestro día y pensamos en qué hacer y en qué orden, sin embargo, es exactamente cómo funciona nuestro cerebro a nivel funcional. Pero recuerda, eso no es multitarea, es solo un cambio rápido de contexto.

Con esto en mente, echemos un vistazo más de cerca a cómo funciona la programación asíncrona en JavaScript.

Ahora a la codificación :

Hay varias formas de realizar la programación asíncrona en JavaScript/Typescript, como mencioné al principio de este artículo, incluido el uso de: devoluciones de llamada , eventos, promesas, asíncrono/espera.

  • Una devolución de llamada es una función que se pasa como argumento a otra función y se ejecuta después de que se haya completado la función externa. Por ejemplo:
  • function greet(name, callback) {
      console.log(`Hello, ${name}!`);
      callback();
    }
    
    function sayGoodbye() {
      console.log("Goodbye!");
    }
    
    greet("John", sayGoodbye);
    // Output: "Hello, John!"
    // Output: "Goodbye!"
    

  • Un evento es una señal de que algo ha sucedido y un oyente es una función que se ejecuta en respuesta a ese evento. Por ejemplo:
  • const button = document.querySelector("button");
    
    button.addEventListener("click", () => {
      console.log("Button was clicked!");
    });
    

  • Una promesa representa el resultado de una operación asíncrona y puede resolverse (con éxito) o rechazarse (fallida), al igual que las promesas de la vida real; cuando haces una promesa o la cumples (resuelve) o no la cumples (rechazar).
    Las promesas se pueden usar para simplificar el proceso de encadenar operaciones asíncronas. Por ejemplo:
  • const promise = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("Completed Async Task");
      }, 1000);
    });
    
    promise.then((result) => {
      console.log(result);
    });
    // Output: "Async task completed" (after 1 second)
    

  • Async/await: una característica de JavaScript que permite el uso de la sintaxis async/await para hacer que el código asíncrono se vea y se comporte como código sincronizado. Async/await se basa en promesas y facilita el trabajo con código asíncrono.
  • async function greet(name) {
      return `Hello, ${name}!`;
    }
    
    async function main() {
      const greeting = await greet("John");
      console.log(greeting);
    }
    
    main();
    // Output: "Hello, John!"
    

En general, la programación asíncrona permite la ejecución de múltiples tareas mientras mantiene la naturaleza de subproceso único del lenguaje. Permite un programa más receptivo y eficiente al permitir que el subproceso principal continúe ejecutándose mientras espera que se completen otras tareas.

Si te gusta este contenido no dudes en seguir. Hay muchos más proyectos entre manos sobre los que planeo escribir en un futuro próximo. Hasta entonces,

¡Gracias por leer!