Clase 3 - Programación sincrónica y asincrónica

Descargar como pptx, pdf o txt
Descargar como pptx, pdf o txt
Está en la página 1de 63

Clase 3.

Programación
Backend
Programación
sincrónica y
asincrónica
● Repasar las funciones en
Javascript y conocer las nuevas
declaraciones
● Comprender lo que es un callback
y las promesas de JS
OBJETIVOS DE LA ● Conocer el concepto y diferencias
CLASE entre programación sincrónica y
asincrónica en Javascript
CRONOGRAMA DEL
CURSO
Clase 2 Clase 3 Clase 4

Principios básiclos de Programación


Manejo de Archivos en
Javascript sincrónica y asincrónica
Javascript
Funciones
Repasando...
Funciones en Javascript
Declaración de
funciones
Las funciones en Javascript tienen varias particularidades
con respecto a otros lenguajes. Recordemos las formas para
declarar una función:

Estilo clásico:
function mostrar(params) {
console.log(params)
}

Llamada a la función: mostrar(args)


Declaración de
funciones
Al ser Javascript un lenguaje que
no requiere especificar el tipo
de dato de sus variables (tipado
dinámico), tampoco es necesario
especificar el tipo de dato que
devuelven las funciones, ni el
tipo de dato de los parámetros
que éstas reciben
Las funciones también son
objetos
En JavaScript las funciones se comportan como objetos:
es posible asignar una declaración de función a una variable.

const mostrar = function(params) {


console.log(params)
}

La podemos ejecutar de la misma forma que una función


clásica.
Funciones 2.0
Nueva declaración de
funciones
La nueva sintaxis consiste en declarar únicamente los
parámetros, y luego conectarlos con el cuerpo de la función
mediante el operador => (flecha gorda, o ‘fat arrow’ en
inglés). Veamos un ejemplo:

Nuevo estilo (simplificado):


const mostrar = (params) => {
console.log(params)
}
Funciones de un solo parámetro
En el caso de que la función reciba un solo parámetro, los
paréntesis se vuelven opcionales, pudiendo escribir:

const mostrar = params => {


console.log(params)
}

La función se podrá usar de la misma manera que las


anteriores
Funciones de una sola instrucción
En el caso de que el cuerpo de la función conste de una
única instrucción, las llaves se vuelven opcionales, el
cuerpo se puede escribir en la misma línea de la declaración y
el resultado de computar esa única línea se devuelve como
resultado de la función, como si tuviera un “return” adelante.
A esto se lo conoce como “return implícito”.

const mostrar = params => console.log(params)

En este caso la función devolvería “undefined” ya que


Return implícito

Un ejemplo igualmente trivial pero más ilustrativo de


return implícito sería el siguiente:
Callbacks
Callbacks..?
Funciones como
parámetros, claro
Funciones como
parámetros..?!
Concepto
Como hemos visto, en Javascript es posible asignar una
función a una variable. Esto es porque internamente, las
funciones también son objetos (y las variables,
referencias a esos objetos). Es por esto que Javascript
nos permite hacer que una función reciba como
parámetro una referencia a otra función.
Ejemplos
Y como ya sabemos, donde puedo usar una variable puedo
también usar directamente el contenido de esa variable.
En el ejemplo, la función ‘ejecutar’ recibe una función
anónima, y la ejecuta.

Esto también funciona con funciones anónimas con


parámetros
Definiendo...

● Un callback es una función que se envía como


argumento a otra función.

● La intención es que la función que hace de


receptora ejecute la función que se le está
pasando por parámetro.

● Podemos decir que la función “ejecutar” que


usamos en el punto anterior “recibe un callback”.
¡Ejemplo!
Imaginemos que queremos que al finalizar una operación se
ejecute un cierto código:
● Por ejemplo, queremos escribir un archivo y registrar en un
log la hora en que se termine de escribir.
● Es probable que no se pueda saber con exactitud en qué
momento va a finalizar.
● En algunos casos (ya veremos en cuáles) no podemos
simplemente ejecutar la de escritura y luego, a
continuación, guardar el log.
● En estos escenarios, las funciones deben recibir como último
parámetro un callback, que (por convención) será ejecutado
al finalizar la ejecución de la función.

Veamos una función inventada para entenderlo:


Ejemplo Callback
function escribirYLoguear(texto, callbackParaLoguear) {
// simulamos que escribimos en un archivo!
console.log(texto)
// al finalizar, ejecutamos el callback
callbackParaLoguear('archivo escrito con éxito')
}

escribirYLoguear('hola mundo de los callbacks!', (mensajeParaLoguear) => {


const fecha = new Date().toLocaleDateString()
console.log(`${fecha}: ${mensajeParaLoguear}`)
})

En este ejemplo, “callbackParaLoguear” es una función anónima enviada como


argumento a la función “escribirYLoguear” que obtiene la fecha de grabación y muestra
un mensaje por pantalla
¡Vamos al código!
➢ Definiremos una función llamada operación que reciba como
parámetro dos valores y una función con la operación que va a
realizar. Deberá retornar el resultado.

➢ Definiremos las siguientes funciones: suma, resta, multiplicación,


división y módulo. Estas recibirán dos valores y devolverán el
resultado. Serán pasadas como parámetro en la llamada a la
función operación

➢ Todas las funciones tendrán que ser realizadas con sintaxis flecha.
Callbacks: Algunas
convenciones
● El callback siempre es el último parámetro.
● El callback suele ser una función que recibe dos
parámetros.
● La función llama al callback al terminar de ejecutar
todas sus operaciones.
● Si la operación fue exitosa, la función llamará al
callback pasando null como primer parámetro y si
generó algún resultado este se pasará como segundo
parámetro.
● Si la operación resultó en un error, la función
Ejemplo convenciones

Desde el lado del callback, estas funciones deberán


saber cómo manejar los parámetros. Por este motivo,
nos encontraremos muy a menudo con la siguiente
estructura
Callbacks anidados
Concepto
● Es un fragmento de código en el que una
función llama a un callback, y este a otro
callback, y este a otro, y así sucesivamente.
● Son operaciones encadenadas, en serie.
● Si el nivel de anidamiento es grande, se puede
producir el llamado callback hell ó infierno de
callbacks. También se conoce como pyramid of
doom ó pirámide de la perdición.
Ejemplo Callback
anidado
¡Atención!
A tipo de estructura de código se le ha denominado
callbacks hell o pyramid of doom, ya que las funciones
se van encadenando de forma que la indentación del código
se vuelve bastante prominente y dificulta la comprensión
del mismo.
Promesas
Promesas
● Una Promesa es un objeto que encapsula una operación, y
que permite definir acciones a tomar luego de finalizada
dicha operación, según el resultado de la misma. Para ello,
permite asociar manejadores que actuarán sobre un
eventual valor (resultado) en caso de éxito, o la razón de
falla (error) en caso de una falla.
● Al igual que con los callbacks, este mecanismo permite
definir desde afuera de una función un bloque de código
que se ejecutará dentro de esa función, dependiendo del
resultado. A diferencia de los callbacks, en este caso se
definirán dos manejadores en lugar de uno solo. Esto
permite evitar callback hells como veremos más adelante.
Estados de una promesa
El estado inicial de una promesa es:
● Pendiente (pending)
Una vez que la operación contenida se resuelve, el estado de
la promesa pasa a:
● Cumplida (fulfilled): la operación salió bien, y su
resultado será manejado por el callback asignado
mediante el método .then().
● Rechazada (rejected): la operación falló, y su error será
manejado por el callback asignado mediante el
método .catch().
Promesas: creación
function dividir(dividendo, divisor) {
return new Promise((resolve, reject) => {
if (divisor == 0) {
reject('no se puede dividir por cero')
} else {
resolve(dividendo / divisor)
}
})
}
Promesas: uso (sale bien)
dividir(10, 0)
.then(resultado => {
console.log(`resultado: ${resultado}`)
})
.catch(error => {
console.log(`error: ${error}`)
})

// muestra por pantalla:


// resultado: 5
Promesas: uso (sale mal)
dividir(10, 0)
.then(resultado => {
console.log(`resultado: ${resultado}`)
})
.catch(error => {
console.log(`error: ${error}`)
})

// muestra por pantalla:


// error: no se puede dividir por cero
Encadenamiento de
Una llamada promesas
a promise.then() devuelve otra promesa, para
que podamos llamar al siguiente .then().
¡Vamos al código!
Determinaremos en cada caso la salida que se registra en la consola

Promise.resolve(20) Promise.resolve(10) Promise.reject(30)


.then( x => x + 1 ) .then( x => x + 1 ) .then( x => x + 1 )
.then( x => x * 2 ) .then( x => x * 2 ) .then( x => x * 2 )
.then( x => { .then( x => { .then( x => {
if(x==22) throw 'Error' if(x==22) throw 'Error' if(x==22) throw 'Error'
else return 80 else return 80 else return 80
}) }) })
.then( x => 30 ) .then( x => 30 ) .then( x => 30 )
.then( x => x / 2 ) .then( x => x / 2 ) .then( x => x / 2 )
.then( console.log ) .then( console.log ) .then( console.log )
.catch( console.log ) .catch( console.log ) .catch( console.log )

Observación: Promise.resolve(arg) devuelve una promesa que siempre


se resolverá en forma exitosa, y que devolverá como resultado el valor
recibido como argumento.

BREAK
¡5/10 MINUTOS Y
VOLVEMOS!
Sincronismo vs Asincronismo
Ejecución sincrónica vs.
ejecución asincrónica
Ejecución Sincrónica:
Repasemos
● Cuando escribimos más de una instrucción en un programa,
esperamos 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.
● Si una instrucción es una llamada a otra función, la
ejecución se pausa y se procede a ejecutar esa función.
● Sólo una vez ejecutadas todas las instrucciones de esa
función, el programa retomará con el flujo de instrucciones
que venía ejecutando antes.
Ejemplo Ejecución Sincrónica
● 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.

● 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
Comportamiento de una
función:
Bloqueante vs no-
bloqueante
Cuando alguna de las instrucciones dentro de una
función intente acceder a un recurso que se encuentre
fuera del programa (por ejemplo, enviar un mensaje
por la red, o leer un archivo del disco) nos
encontraremos con dos maneras distintas de hacerlo:
en forma bloqueante, o en forma no-bloqueante
(blocking o non-blocking).
Operaciones bloqueantes
● En la mayoría de los casos, precisamos que el programa
ejecute todas sus operaciones en forma secuencial, y sólo
comenzar una instrucción luego de haber terminado la
anterior.
● A las operaciones que obligan al programa a esperar a que
se finalicen antes de pasar a ejecutar la siguiente instrucción
se las conoce como bloqueantes.
● Este tipo de operaciones permiten que el programa se
comporte de la manera más intuitiva.
● Permiten la ejecución de una sola operación en simultáneo.
● A este tipo de ejecución se la conoce como sincrónica.
Operaciones no-
● bloqueantes
En algunos casos esperar a que una operación termine para
iniciar la siguiente podría causar grandes demoras en la
ejecución del programa.
● Por eso que Javascript ofrece una segunda opción: las
operaciones no bloqueantes.
● Este tipo de operaciones permiten que, una vez iniciadas, el
programa pueda continuar con la siguiente instrucción, sin
esperar a que finalice la anterior.
● 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.
Concepto Ejecución
Asincrónica
● Para poder usar funciones que realicen operaciones no
bloqueantes debemos aprender a usarlas adecuadamente,
sin generar efectos adversos en forma accidental.
● Cuando el código que se ejecuta en forma sincrónica,
establecer el orden de ejecución consiste en decidir qué
instrucción escribir primero.
● 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.
Ejemplo Ejecución
Asincrónica
const escribirArchivo = require('./escrArch.js')
En el ejemplo no se bloquea la
console.log('inicio del programa') ejecución normal del programa
y se permite que este se siga
// el creador de esta funcion la definió
// como no bloqueante. recibe un callback que
ejecutando.
// se ejecutará al finalizar la escritura. La ejecución de la operación de
escribirArchivo('hola mundo', () => { escritura “comienza” e
console.log('terminé de escribir el archivo')
})
inmediatamente cede el control a
la siguiente instrucción, que
console.log('fin del programa')
escribe por pantalla el mensaje de
// se mostrará por pantalla: finalización.
// > inicio del programa Cuando la operación de escritura
// > fin del programa
// > terminé de escribir el archivo
termina, ejecuta el callback que
informará por pantalla que la
Ejemplo Ejecución Asincrónica :
Aclaración
Si queremos que el mensaje de ‘finalizado’ salga después de
haber grabado el archivo, anidaremos las instrucciones
dentro del callback de la siguiente manera:
escribirArchivo('hola mundo', () => {
console.log('terminé de escribir el archivo')
console.log('fin del programa')
})

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.
Timers
setTimeout
setTimeout
❏ setTimeout(function, milliseconds, param1,
param2, ...)
➢ Es una función nativa, no hace falta importarla.
➢ La función setTimeout() recibe un callback, y lo ejecuta
después de un número específico de milisegundos.
➢ Trabaja sobre un modelo asincrónico no bloqueante.
setInterval
setInterval
❏ setInterval(cb, milliseconds, param1, param2, ...):
Object
➢ Es una función nativa, no hace falta importarla.
➢ La función setInterval() también recibe un callback, pero
a diferencia de setTimeout() lo ejecuta una y otra vez
cada vez que se cumple la cantidad de milisegundos
indicada.
➢ Trabaja sobre un modelo asincrónico no bloqueante.
➢ El método setInterval() continuará llamando al callback
hasta que se llame a clearInterval() o se cierre la
ventana.
➢ El objeto devuelto por setInterval() se usa como
¿PREGUN
TAS?
¡MUCHAS
GRACIAS!
Resumen de lo visto en clase
hoy:
-Funciones
-Callbacks
-Promesas
-Ejecución
sincrónica/asincrónica
OPINA Y VALORA
ESTA CLASE
#DEMOCRATIZANDOLAED
UCACIÓN

También podría gustarte