En la sección anterior vimos cómo dividir nuestra aplicación en múltiples archivos con la finalidad de que todo el código se vea más ordenado. Ahora vamos a crear controladores que son funciones que ejecutan los enrutadores, los cuales a su vez manejan las solicitudes HTTP de nuestra aplicación. De momento, esto se ve fácil porque es tan solo una sola línea de código, haciendo referencia a las rutas GET, POST, PUT y DELETE.
Si te perdiste la parte 4 puedo ir aquí.
El problema puede surgir, si agregamos más cantidad de líneas entonces sería algo difícil de leer. Podemos tener consultas, validaciones y mucha lógica a través de estas consultas. Una mejor forma de hacer esto, es separar las funciones que ejecutan estas rutas, porque al final son funciones que pueden ser reutilizables.
Para empezar vamos a ir a nuestro archivo de employees.routes.js
y cortar la función que maneje una ruta de la siguiente manera:
router.get('/employees', (req, res) => res.send('obteniendo empleados'))
Esta es la ruta completa, que es manejada por su función correspondiente. Ahora lo que vamos a hacer es cortar la función, para esto, cada función la vamos a ubicar en una carpeta que se llamará controllers
.
Creando nuestro archivo para las funciones controladoras
Dentro de la carpeta src
vamos a crear una nueva carpeta llamada controllers
. Dentro de la carpeta controllers
vamos a crear un archivo que se va a llamar employees.controllers.js
.
Acá se podría confundir la similitud que existe entre el archivo employees.routes.js
y employees.controllers.js
, es tan solo un nombre de referencia, no existe una relación realmente.
Pero es una forma práctica que nosotros sabemos que de alguna manera estos dos archivos están relacionados entre sí.
Entonces, como dijimos, vamos a cortar la función de la siguiente manera:
(req, res) => res.send('obteniendo empleados')
Y la vamos a pegar en nuestro archivo employees.controllers.js
.
Ahora lo que vamos a hacer es nombrar esta función de la siguiente manera:
const getEmployees = (req, res) => res.send('obteniendo empleados')
Acá la función que acabamos de cortar la vamos a almacenar en una constante, esto es lo mismo que antes, solamente que ahora se está guardando en una constante llamada getEmployees
. Esto es un ejemplo de cómo crear controladores en Node.js.
Lo mismo vamos a hacer con el resto de las rutas:
Para exportar múltiples constantes utilizando module.exports
, para esto se puede crear un objeto que contenga todas las constantes que se desea exportar. Por ejemplo:
const getEmployees = (req, res) => res.send('obteniendo empleados')
const createEmployees = (req, res) => res.send('agregando empleados')
const updateEmployees = (req, res) => res.send('actualizando empleados')
const deleteEmployees = (req, res) => res.send('eliminando empleados')
module.exports = {
getEmployees,
createEmployees,
updateEmployees,
deleteEmployees
}
Este código crea un objeto que contiene las cuatro constantes y las exporta usando module.exports
. Cada constante se nombra como una propiedad del objeto, y se asigna el valor de la constante a la propiedad correspondiente.
Importando todas las funciones controladoras
Ahora, desde otro archivo, se puede importar todas estas constantes usando la sintaxis require()
y desestructuración, como por ejemplo:
const { getEmployees, createEmployees, updateEmployees, deleteEmployees } = require("../controllers/employees.controllers.js")
Este código importa el objeto exportado del archivo que contiene las constantes de los controladores, y utiliza la desestructuración para asignar cada constante a su propia variable. A partir de ahí, se pueden llamar a las funciones como se desee.
router.get( '/employees', getEmployees )
router.post( '/employees', createEmployees )
router.put( '/employees', updateEmployees )
router.delete( '/employees', deleteEmployees )
Al final estas rutas que tenemos aquí son más legibles, es decir que cuando visite la ruta GET
va a llamar a la función, getEmployees
cuando visite la ruta POST
va a llamar a la función, createEmployees
cuando visite la ruta PUT
va a llamar a la función updateEmployees
y así.
Para comprobar que todo funciona correctamente vamos a ir a la extensión Thunder client y vamos a probar cada una de las rutas.
Creando el controlador para la ruta /ping
De esta forma ya tenemos los controladores, y es aquí donde vamos a importar los archivos de conexión con la base de datos. De momento no tenemos ningún archivo, pero vamos a hacer lo mismo que hicimos con index.routes.js
. Este archivo también tiene su función qué es la que utiliza para conectarse a la base de datos y mostrar el resultado "pong"
.
router.get('/ping',
async (req, res) => {
try {
const result = await query('SELECT "pong" AS resultado')
res.json(result[0])
} catch (error) {
console.error(error)
res.status(500).send('Error al obtener la información')
}
}
)
Esta función la podemos separar, vamos a crear otro archivo que se llame index.controller.js
y vamos a hacer lo mismo que hicimos anteriormente con el resto de las rutas, cortar la función y pegarla en el archivo, index.controller.js
a esta función lo vamos a llamar, ping
es decir la vamos a guardar en una constante llamada ping
. Como se muestra a continuación:
const ping = async (req, res) => {
try {
const result = await query('SELECT "pong" AS resultado')
res.json(result[0])
} catch (error) {
console.error(error)
res.status(500).send('Error al obtener la información')
}
}
De igual manera la vamos a exportar usando module.exports
.
module.exports = ping
Ahora la tenemos que importar, para esto vamos al archivo index.routes.js
y escribimos lo siguiente:
const { ping } = require( '../controllers/index.controller.js' )
Acá lo que estamos utilizando la desestructuración y requiriendo el archivo index.controller.js
que está dentro de la carpeta controllers
, para ubicar el archivo subimos dos niveles ../controllers/index.controller.js
usando la sintaxis de dos puntos y desde allí importar ping
.
Para ejecutar de la siguiente forma:
router.get('/ping', ping )
Conexión a la base de datos
Si en este momento guardamos, seguramente nos va a dar un error cuando visitemos la ruta /ping
en el navegador, la función se va a ejecutar, pero esta función está necesitando la conexión a la base de datos. Para esto necesitamos el método query()
que está asociado con pool
que es la conexión a la base de datos. Para esto vamos a cortar las siguientes tres líneas que son las que nos permiten hacer la conexión a nuestra base de datos.
const pool = require('../db.js')
const util = require('util')
const query = util.promisify(pool.query).bind(pool)
Y las pegamos en el archivo index.controller.js
de controladores.
Ahora, para comprobar que esto está funcionando correctamente, vamos a visitar a través del navegador la ruta /ping
y nos tiene que dar como resultado pong
.