Documentos de Académico
Documentos de Profesional
Documentos de Cultura
ejecución asincrónica
Teoría
Introducción
Como ya vimos en el primer apunte de manejo de archivos, NodeJS nos ofrece múltiples
funciones para realizar operaciones sobre archivos con mucha facilidad. Ya hemos visto las
versiones sincrónicas y nos ha quedado pendiente ver las asincrónicas. Pero ¿Qué significa
que una función sea asincrónica? Veamos un poco de qué se trata.
Ejecución sincrónica
Siempre que escribamos más de una instrucción en un programa, acostumbramos esperar que
las instrucciones se ejecuten comenzando desde la primera línea, una por una, de arriba hacia
abajo, hasta llegar al final del bloque de código. En el caso de que una de esas instrucciones
sea una llamada a otra función, el orden de ejecución se pausa, y se procede a ejecutar las
instrucciones dentro de esa función. Sólo una vez ejecutadas todas las instrucciones de esa
función, es que el programa retomará con el flujo de instrucciones que venía ejecutando antes.
En todo momento, sólo se están ejecutando las instrucciones de una sola de las
funciones a la vez. O sea, debe finalizar una función para poder continuar con la otra.
Siguiendo esta idea, el fin de una función marca el inicio de la siguiente, y el fin de ésta, el
inicio de la que le sigue, y así sucesivamente, describiendo una secuencia que ocurre en una
única línea de tiempo.
Ejemplo
function funA(){
console.log(1)
funB()
console.log(2)
}
function funB(){
console.log(3)
funC()
console.log(4)
}
function funC(){
console.log(5)
}
1
3
5
4
2
Operaciones bloqueantes
Este tipo de operaciones permiten que el programa se comporte de la manera más intuitiva, es
decir, siguiendo las reglas establecidas en el punto anterior (ejecución sincrónica).
De esta manera si quisiéramos, por ejemplo, escribir un texto dentro de un archivo, podríamos
hacer lo siguiente:
console.log('comenzando...')
fs.writeFileSync(arch, texto)
console.log(`${arch} grabado con éxito`)
console.log(`finalizado`)
Si lo ejecutamos, obtendremos un resultado similar a éste:
comenzando...
f1.txt grabado con éxito
finalizado
Operaciones no-bloqueantes
Ahora bien, en algunos casos esperar a que una operación termine para iniciar la siguiente
puede no ser la mejor idea, ya que esto podría causar grandes demoras en la ejecución del
programa. Es por eso que NodeJS ofrece una segunda opción: las operaciones no
bloqueantes.
Este tipo de operaciones permite que, una vez iniciadas, el programa pueda continuar con la
siguiente instrucción, sin esperar a que finalice la anterior. O sea, permite la ejecución de varias
operaciones en paralelo, sucediendo al mismo tiempo. A este tipo de ejecución se la conoce
como asincrónica.
Ejecución asincrónica
Para poder usar funciones que realicen operaciones no bloqueantes debemos aprender a
usarlas adecuadamente, y no generar efectos adversos en forma accidental.
Cuando se trata de código que se ejecuta en forma sincrónica, establecer el orden de ejecución
se vuelve tan fácil como decidir qué instrucción escribir primero. Sin embargo, cuando se trata
de ejecución asincrónica, sólo sabemos en qué orden comenzarán su ejecución las
instrucciones, pero no sabemos en qué momento ni en qué orden terminarán de ejecutarse.
Veamos el siguiente ejemplo, utilizando la versión no-bloqueante de la función de escritura en
archivos:
console.log('comenzando...')
console.log(`finalizado`)
Si lo ejecutamos, obtendremos lo siguiente:
comenzando...
finalizado
f1.txt grabado con éxito
...
Esto funciona porque lo (único) que podemos controlar en este tipo de operaciones es que el
callback siempre se ejecuta luego de finalizar todas las demás instrucciones involucradas en
ese llamado.
Si quieren conocer más en profundidad sobre este tema (tan complejo como interesante!) el
cual no abordaremos en más detalle durante la cursada, pueden buscar sobre el “event loop”,
que es el sistema que administra el orden en que se ejecutan las instrucciones en NodeJS.
Manejo de Archivos (2da parte): forma asincrónica
Teoría
Introducción
Ya vimos que NodeJS ofrece un módulo que nos permite trabajar sobre el sistema de archivos
de nuestro sistema operativo, ya aprendimos sobre las operaciones más comunes que solemos
realizar sobre archivos, y ya vimos cómo realizarlas en forma sincrónica. Nos resta entonces
revisar sus versiones asincrónicas.
Notarán que todas las funciones de este apunte tienen el mismo nombre que sus versiones
sincrónicas, pero sin la palabra “Sync” al final, y en cambio, todas reciben un nuevo último
parámetro: un callback.
En este caso, la mayoría de los callbacks siguen la convención de que el callback deberá
recibir un primer parámetro destinado al error (si lo hubiere) para saber cómo manejarlo.
Dado que estas funciones poseen un parámetro que nos permite elegir cómo manejar los
errores que pueden surgir de su ejecución, no será necesario ejecutarlas utilizando try /
catch.
Leer un archivo
Para leer un archivo usaremos la función readFile(ruta, encoding, callback). Recibe los
mismos parámetros que su versión sincrónica, más el callback.
Ejemplo de uso:
Sobreescribir un archivo
Para escribir un archivo usaremos la función writeFile(ruta, datos, callback). Recibe
los mismos parámetros que su versión sincrónica, más el callback, que en este caso, solo
precisa recibir un parámetro para manejar algún eventual error.
Ejemplo de uso:
Ejemplo de uso:
Ejemplo de uso:
Borrar un archivo
Para borrar un archivo usaremos la función unlink(ruta, callback). El mismo parámetro
que su versión sincrónica, más el callback, que en este caso, solo precisa recibir un parámetro
para manejar algún eventual error.
Ejemplo de uso:
Ejemplo de uso:
Introducción
Ya vimos que NodeJS ofrece el módulo fs que nos permite operar tanto de forma sincrónica
como asincrónica. Así mismo, dentro del paradigma asincrónico, inicialmente ofrecía funciones
que reciben un callback para manejar el asincronismo. Con la llegada de las promesas, JS
agregó un módulo dentro de fs, que añade versiones de las funciones asincrónicas, pero que
en lugar de recibir callbacks, operan mediante promesas. Veremos aquí algunos ejemplos con
las mismas funciones sobre las que venimos trabajando. Inicialmente, las promesas se usaron
con su sintaxis nativa, y luego se agregó en una versión posterior una sintaxis simplificada
utilizando las (entonces) nuevas palabras reservadas “async” y “await”. Nos concentraremos
principalmente en está última.
Leer un archivo
Para leer un archivo usaremos la función readFile(ruta, encoding). Recibe los mismos
parámetros que su versión sincrónica.
Ejemplo de uso:
Recordar que debemos anteponer la palabra “await” al llamado a la función para que ésta se
comporte de manera bloqueante. Si se omitiera la palabra “await” la instrucción
console.log(contenido) se ejecutaría ANTES de que a la variable contenido se le asigne el
resultado de la operación de lectura del archivo!
Recordar también que la palabra “await” puede usarse ÚNICAMENTE dentro de una función de
tipo “async”
Dado que estas funciones ya no poseen un parámetro que nos permite elegir cómo manejar los
errores que pueden surgir de su ejecución, vuelve a ser necesario ejecutarlas utilizando try /
catch !
Sobreescribir un archivo
Para escribir un archivo usaremos la función writeFile(ruta, datos). Recibe los mismos
parámetros que su versión sincrónica, más el callback, que en este caso, solo precisa recibir un
parámetro para manejar algún eventual error.
Ejemplo de uso:
Renombrar un archivo
Para escribir un archivo usaremos la función rename(rutaVieja, rutaNueva, callback).
Recibe los mismos parámetros que su versión sincrónica, más el callback, que en este caso,
solo precisa recibir un parámetro para manejar algún eventual error.
Ejemplo de uso: