Concurrencia en Javascript
Al estar desarrollando, a veces necesitamos ejecutar varios procesos al mismo tiempo de forma paralela y no secuencial, como solemos hacer. Por ejemplo, cuando programamos una página Web y tenemos que ejecutar una función que puede bloquear el navegador por la gran cantidad de tiempo que tarda en procesarse, necesitamos hacerlo de forma paralela a la aplicación. Estoy escribiendo este artículo porque me he encontrado con este problema mientras desarrollo una aplicación que hace una llamada a una función que tarda más de un minuto en procesarse. Al ejecutar esta función, el navegador se bloquea y necesito reiniciarlo y parar el programa.
Trabajar con threads (hilos) en Javascript no es complicado. De hecho, es más facil de lo que pensáis si utilizamos una librería llamada Concurrent.Thread.js, la cual podemos descargar desde aquí.
Ejemplos
Siempre digo que la mejor manera de aprender a hacer algo es haciéndolo, sobre todo en la programación. Sabemos lo que es la ejecución paralela y sabemos lo que es Javascript, ¿no?. Vamos a ver varios ejemplos en los que os explicaré cómo utilizar esta librería.
Ejemplo 1
Vamos a suponer que tenemos una función Javascript que ejecuta un proceso, el cual consiste en un bucle while(true) que se ejecuta sin fin: function proceso () { while (true) { console.log("HOLA MUNDO"); } }Al hacer la llamada a esta función, el navegador se bloqueará y no nos dejará interactuar con la página. Código completo: <html> <head> <meta charset="UTF-8"> <title>Ejemplo 1 con concurrencia</title> </head> <body> <script type="text/javascript"> function proceso () { while (true) { console.log("HOLA MUNDO"); } } proceso(); </script> Lorem ipsum dolor sit amet, consectetur adipiscing elit. <button>Este botón SÍ se va a mostrar</button> </body> </html>
Os explico un poco lo que pasa en el código: tenemos un ejemplo en el que ejecutamos una función que no finalizará nunca, a menos que cerremos el navegador o la pestaña que hemos abierto. Por esta razón, el texto Lorem ipsum y el botón de abajo nunca se mostrarán en pantalla. Si utilizáramos concurrencia, la función proceso() se ejecutaría en un hilo distinto y sí se mostrarían el texto y el botón, permitiendo al usuario hacer lo que quiera mientras. Veamos el código:
<html> <head> <meta charset="UTF-8"> <title>Ejemplo 1 con concurrencia</title> <script src="../js/Concurrent.Thread.js"></script> </head> <body> <script type="text/javascript"> function proceso () { while (true) { console.log("HOLA MUNDO"); } } Concurrent.Thread.create(proceso); </script> Lorem ipsum dolor sit amet, consectetur adipiscing elit. <button>Este botón SÍ se va a mostrar</button> </body> </html>El método para crear un nuevo thread es Concurrent.Thread.create();. Con él, ejecutamos la funciónproceso()en segundo plano para no perjudicar al usuario.
Ejemplo 2
Este ejemplo es igual que el anterior, pero en lugar de ejecutar la función proceso sin ningún parámetro de entrada, vamos a introducir una variable, que será la que se imprimirá en la consola del navegador:
function proceso (parametro_texto) { while (true) { console.log(parametro_texto); } }Como se puede observar en el código, simplemente hemos añadido un parámetro. A continuación, veremos cómo hacer esto mismo pero con concurrencia. La sintaxis es la siguiente: Concurrent.Thread.create(funcion, parametro);, tal y como vemos a continuación: <html> <head> <meta charset="UTF-8"> <title>Ejemplo 2 con concurrencia</title> <script src="../js/Concurrent.Thread.js"></script> </head> <body> <script type="text/javascript"> function proceso (parametro_texto) { while (true) { console.log(parametro_texto); } } Concurrent.Thread.create(proceso, "HOLA MUNDO"); </script> Lorem ipsum dolor sit amet, consectetur adipiscing elit. <button>Este botón SÍ se va a mostrar</button> </body> </html>
Al ejecutar la función de manera concurrente, la página funcionará correctamente y sin bloquear el navegador.
Todo el código utilizado en este tutorial está subido en un repositorio en Github. Descargadlo y probadlo vosotros mismos.¡Saludos!