Conocer y comprender cómo se realizan las conexiones hacia los servidores a través de internet y sus implicaciones en el desarrollo de servidores

1

Bienvenida y presentación del curso

2

Qué es Node y cómo instalarlo

3

¿Qué son y cómo se usan las peticiones HTTP?

4

Métodos, cabeceras y estados

5

Cuerpo y query de la petición

Crear un servidor HTTP en Javascript, y comenzar a escuchar y responder peticiones desde un cliente .

6

Crear un servidor HTTP desde NodeJS

7

¿Cómo pueden venir las peticiones?

8

Recibir información desde el cliente: Body y Query

9

Información contextual: Leer las cabeceras

10

Tipos de respuesta: Vacía, plana, con datos y estructurada

11

Respuestas coherentes

12

Servir archivos estáticos

13

Errores: Cómo presentarlos e implicaciones en la seguridad

Comprender y desarrollar la arquitectura básica de un backend en NodeJS, y comunicarse entre módulos

14

Conceptualmente: Rutas, controladores y bases de datos

15

Rutas y capa de red: Responsabilidades y límites

16

Controladores: Definiendo la lógica de negocio

17

Almacenando la información en una base de datos

Utilizar una base de datos para definir, modelar, almacenar y recuperar la información de nuestra aplicación

18

Tipos de Bases de Datos: Relacionales y No Relacionales

19

Crear y Configurar tu Base de Datos con MongoDB

20

MongoDB: Almacenar y leer datos

21

MongoDB: Actualizar datos

22

MongoDB: Consultar datos

23

MongoDB: Eliminar Datos

24

Gestionar conexiones a la base de datos desde la API

Uso de entidades para crear aplicaciones escalables

25

Escalando la arquitectura: Múltiples entidades

26

Relacionando nuestras entidades

27

Cómo recibir ficheros desde NodeJS

28

Guardar el fichero en el servidor

Conocer el protocolo de websockets, e implementar comunicación cliente/servidor con SocketIO.

29

WebSockets: Qué son, por qué son interesantes y cómo usarlos

30

Manejo de Websockets con NodeJS

31

Conectar la API al servidor de WebSockets

Revisión de lo aprendido, y próximos pasos

32

Revisión y próximos pasos

33

Tips para escalar nuestro proyecto

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Controladores: Definiendo la lógica de negocio

16/33
Recursos

Aportes 44

Preguntas 12

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

o inicia sesión.

El error de el minuto 06:55 se debe a que escribió mal return, el puso retrun si es posible hacerlo en una sola linea

return reject('Los datos son incorrectos');

Aquí les dejo una propuesta del código utilizando async-await

post(async (req, res) => {
    try{
        const fullMessage = await controller.addMessage(req.body.user, req.body.message)
        response.success(req, res, 201, fullMessage)
    }catch(error){
        response.error(req,res,null,error)
    }
})

Hola Devs:
-Me propuse como reto apartir de esta clase, realizar todo el proyecto con TypeScript, es mi primera vez con TS, pero quiero darle, si alguien mas se anima, les dejare en cada clase apartir de ahora, el link del commit exacto de la clase, asi pueden checar mi solucion usando TS.
-Aca les dejo mi avance:
Capa de Network del componente Message

Capa del Controller del componente Message

-Estoy abierto a mejoras o PR, soy nuevo con TS por si ven alguna mejora, aca les dejo el commit exacto de esta clase: Click Aqui
"Tambien pueden checar la config que use para trabajar con TS, por si quieren checar"
-Recuerda, #NuncaParesDeAprender 💚

Ahora ya le encuentro utilidad al curso de Fundamentos de JS, muy buena clase

Hola que tal, estoy utilizando las promesas con async/await

Network:

router.post('/', async (req, res) => {
    try {
        const body = await Controller.addMessage(req.body.user, req.body.message);
        await response.success(req, res, { error: null, body }, 200);
    } catch (error) {
        console.error(`[POST/message]: ${error}`);
        await response.error(req, res, { error: 'Error Interno', body: null }, 400);
    }
});

Controller:

const addMessage = (user, message) => new Promise((resolve, reject) => {
    const fullMessage = {
        user,
        message,
        date: new Date()
    };

    if (!user || !message) {
        reject(new Error('se requiere user y message'));
        return;
    }

    resolve(fullMessage)
});

Les comparto los apuntes que llevo hasta ahora, tengo varias funcionalidades que he visto en la documentación y algunos apuntes, espero les sirva 😃

server.js

//Modulos node-express
const express = require('express')
const bodyParser = require('body-parser')

//Modulos locales
const response = require('./network/response')
const router = require('./network/routes')

//Creando la app
const app = express()

//variables de la app
app.set('port', 3000)
//Middlewares
app.use(express.json())
app.use(express.urlencoded({ extended: false }))
//! Router siempre debe de ir al final
//? Ya no vamos a usar el app.use(router)en su vez usaremos el router app
//Rutas
//?Usaremos las rutas de network
router(app)

app.use('/app', express.static('public'))

//Empezando el servidor en el puerto $port
app.listen(app.get('port'))
console.log(`La aplicacion está corriendo en el puerto ${app.get('port')}`)

routes.js

//? Recibe desde server la app (server) y establece la función padre de un router
//? De cada una de las rutas después llama a messages/network quienes envian el mensaje de respuesta
const express = require('express')
const message = require('../components/messages/network')

const routes = function (server) {
	server.use('/message', message)
}

module.exports = routes

network.js

const express = require('express')
const router = express.Router()

// Modulos locales
const response = require('../../network/response')
const controller = require('./controller')

//!||
router.get('/', (req, res) => {
	//console.log(req.headers)
	console.log(req.body)
	console.log(req.query)
	res.header({
		Valor: 'Personalizado',
	})
	//?Enviamos un send desde otras funciones en otro archivo (response)
	if (req.query.error == 'ok') {
		response.error(
			req,
			res,
			'Tu peticion por url no puede ser completada',
			403,
			'Parametro rechazado',
		)
	} else {
		response.success(req, res, 'Hola desde get')
	}
})

//!||
router.post('/', (req, res) => {
	//? Enviamos info de el req a el archivo -> controller lo que retorna una promesa
	//? Después recibimos la response de el archivo response y enviamos success o error
	controller // -> Controller
		.addMessage(req.body.user, req.body.message)
		.then(fullMessage => {
			response.success(req, res, fullMessage, 201, 'Datos recibidos') // -> Response
		})
		.catch(() => {
			response.error(
				// -> Response error
				req,
				res,
				'Informacion invalida',
				403,
				'El usuario no ha introducido datos correctos',
			)
		})
	res.header({
		//-> Envía un header a el cliente
		Valor: 'Personalizado',
	})
})

//!||
router.delete('/', (req, res) => {
	//console.log(req.headers)
	console.log(req.body)
	console.log(req.query)
	res.header({
		Valor: 'Personalizado',
	})
	//?Enviamos un send desde otras funciones en otro archivo (response)
	if (req.query.error == 'ok') {
		response.error(
			req,
			res,
			'Tu peticion por url no puede ser completada',
			403,
			'Parametro rechazado',
		)
	} else {
		response.error(
			req,
			res,
			'hola desde delete aqui te retornaré un 404 :B',
			403,
			'Trataron de usar delete',
		)
	}
})

module.exports = router

controller.js

//?Este archivo recibe informacion desde la network

function addMessage(user, message) {
	return new Promise((resolve, reject) => {
		if (!user || !message) {
			console.error('[MessageController] No hay usuario o mensaje')
			reject('Los datos son incorrectos')
			return false
		}
		const fullMessage = {
			user: user,
			message: message,
			date: new Date(),
		}
		console.log(fullMessage)
		resolve(fullMessage)
	})
}

module.exports = {
	addMessage,
}

responses.js

//? Este archivo es usado dentro de el enrutador para enviar respuestas
//* Server <- routes <- network <- responses

exports.success = function (req, res, message, status) {
	res.status(status || 200).send(message)
}

exports.error = function (req, res, message, status, details) {
	console.log(details)
	res.status(status || 404).send(`Mensaje de error :( "${message}"`)
}

Por fin entiendo más lo del controlador. En el trabajo era tan difícil entender como se conectaba a la capa de presentación.

¡Muchas gracias Profe! 😬👍

Si quieres crear una hora y fecha mas legible, usa esto:

const fullMessage = {
            user,
            message,
            date: new Date().toLocaleString()
			27/02/2021, 12:49:46 p.m.
        }

Cuando trabajamos con javascript y estamos creando un objeto, podemos omitir el nombre de la variable si el valor es igual a la variable es mas claro esto con un ejemplo
const fullMessage = { user, message, date: new Date() }
Esto va devolver
{ user: 'Nicolas', message: 'perrano', date: 2020-09-06T19:32:07.650Z }

Les dejo la manera de hacerlo con try catch funcionado en el caso que tiren error a proposito

en Network

router.post('/message/', async (req, res) => {
  try {
    const fullMessage = await controller.addMessage(req.body.user, req.body.message);
    if (fullMessage) {
      response.success(req, res, fullMessage, 200);
    } else {
      throw Error;
    }
  } catch (error) {
    response.error(req, res, 'error en servidor', 500, 'detalles del error: ninguno, solo probando');
  }

  // res.send({ parametro: req.params, query: req.query });
});

en controller

const addMessage = async (user, message) => {
  //
  try {
    if (!user || !message) {
      console.log('no hay usuario o mensaje');
      throw Error('no hay nada');
    }
    console.log(user);
    console.log(message);

    const fullMessage = {
      message: message,
      user: user,
      date: new Date(),
    };
    return fullMessage;
  } catch (error) {
    console.log('Entra en error ', error);
    return false;
  }
};

Me causa un poco de conflicto, vengo de C# con .net y el controlador es usualmente aquella clase o elemento que recibe la peticion, una vez ahi dependiendo la arquitectura, manda la informacion a un servicio a ser procesada, y despues a un repo para ser almacenada (asi es como suelo trabajar) me causa un poco de conflicto llegar y que haya rutas que reciben la peticion, un controlador que procesa la informacion

controladores=>lógica de negocio

En Controller irán todas las funcionalidades asociada a cada ruta, o cada feature.

¿Que pasa si en la parte de la promesa lo hubiese dejado de la siguiente manera?
.

function addMessage(user, msg) { 
	return new Promise(function(resolve, reject){ 
		if (user && msg) {
			// code goes here...
			resolve('Everything goes right');
		} else {
			// code goes here...
			reject('Oh no an error has occurred');
		}
	});
}

.
Aun que me imagino que por estar trabajando en Node.js tenemos que seguir el patro de Error First. Sin embargo me quede con esa duda, ¿que opinas Carlos?

Les dejo el codigo con async await

router.post('/', async (req, res) => {
    try {
        const fullMessage = await controller.addMessage(req.body.user, req.body.message);
        //  req, res, message, status
        response.success(req, res, fullMessage, 201);
    } catch (error) {
        //  req, res, message, status, details
        response.error(req, res, error, 400, 'Error in controller')
    }
});

porque se puede generar este error?
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:526:11)
at ServerResponse.header (/mnt/d/documentos/programacion/curso_node/node_modules/express/lib/response.js:771:10)
at ServerResponse.send (/mnt/d/documentos/programacion/curso_node/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/mnt/d/documentos/programacion/curso_node/node_modules/express/lib/response.js:267:15)
at ServerResponse.send (/mnt/d/documentos/programacion/curso_node/node_modules/express/lib/response.js:158:21)
at Object.exports.success (/mnt/d/documentos/programacion/curso_node/netwokr/response.js:2:31)
at /mnt/d/documentos/programacion/curso_node/components/message/network.js:24:14
at Layer.handle [as handle_request] (/mnt/d/documentos/programacion/curso_node/node_modules/express/lib/router/layer.js:95:5)
at next (/mnt/d/documentos/programacion/curso_node/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/mnt/d/documentos/programacion/curso_node/node_modules/express/lib/router/route.js:112:3)

Para pasar parámetros sin importar su orden, los podemos pasar a través de un objeto.
function save({ user, message }) {}

uso:
save({ message, user })

No tenemos que preocuparnos por el orden si no solo por cuáles son los que se deben pasar.

Les el codigo con async await

router.post('/', async (req, res) => {
    try {
        const fullMessage = await controller.addMessage(req.body.user, req.body.message);
        //  req, res, message, status
        response.success(req, res, fullMessage, 201);
    } catch (error) {
        //  req, res, message, status, details
        response.error(req, res, error, 400, 'Error in controller')
    }
});

¿Existe alguna dependencia en NPM que ayude a hacer los logs más sencillo? Encuentro poco eficiente tener que escribir [messageController] en los logs para saber de dónde vienen. ¿Habrá alguna dependencia que haga esto or nosotros?

Espectacular.

const express = require('express');
const response = require('../../network/response');
const controller = require('./controller');
const router = express.Router();

router.get('/', (req, res) => {
    console.log(req.headers);
    res.header({
        "custom-header": "Nuestro valor personalizado"
    })
    response.success(req, res, 'Error inesperado');
});

router.post('/', (req, res) => {
    controller.addMessage(req.body.user, req.body.message)
        .then( (fullMessage) => {
            response.success(req, res, fullMessage, 201);
        })
        .catch( e => {
            response.error(req, res, 'Informacion invalida', 400, 'Error en el controller');
        })
});

module.exports = router;

Qué gran curso!! Con esta sola clase se me han resuelto muchas dudas que tenía de cursos más avanzados de node.js. Grande Carlos!

2:298 la macro Copiar línea. Para copiar la línea actual hacía arriba o abajo. Windows y Linux. Shift + Alt + ↓

A modo de edición podrían poner un bloque abajo, cuando ocupan macros, para aprender como escribir código mas rápido y eficiente. Ya que el profesional lo hace de manera intuitiva y nos interesa.

Creamos un nuevo archivo controller.js dentro de la carpeta message el cual contendrá toda la lógica de negocio del componente message y será exportado como un modulo
components/message/controller.js:

function addMessage (user,message){
    const fullMessage = {
        user,
        message,
        date: new Date(),
    }

    return new Promise((res,rej)=> {
        if (!user || !message){
            rej('data incorrecta')
            return 
	}
        res(fullMessage)
    })
}

module.exports = {
    addMessage,
}

luego procedemos a importar el controlador en el archivo network.js en el componente message y a modificar el POST recibiendo un user y un message en el cuerpo del body del request

{
  "user": "Juan",
  "message": "Hello people"
}

como el retorno del controller es una promesa, modificamos la lógica para que todo funcione correctamente
components/message/network.js:

const express = require('express');
const response = require('../../network/response')
const controller = require('../message/controller')

var app = express()
app.get('/', (req,res)=> {
    res.header({
        "custom-header": "mi propia cabecera personalizada"
    })
    response.sucess(req,res,'respuesta exitosa del get')
})

app.post('/', (req,res)=> {
    controller.addMessage(req.body.user, req.body.message) 
        .then(fullMessage => response.sucess(req,res, fullMessage,201)) 
        .catch(error => response.error(req,res, error,500,"detalles del error")) 
})

module.exports = app 

si hacemos una petición POST a la url “/message” con el cuerpo del body

{ "user": "juan", "message": "Hello people" }

vemos como respuesta de parte del servidor

{
  "error": "",
     "body": {
       "user": "Juan",
       "message": "Hello people",
       "date": "2022-11-04T19:37:13.352Z"
     }
}

si hacemos la misma petición pero no le mandamos nada en el cuerpo del body, vemos como respuesta de parte del servidor

{
	"error": "data incorrecta",
	"body": ""
}

formato util para fechas:

  date: new Date().toLocaleString() 

devuelve:

 date: '26/10/2022, 3:02:41 p. m.'

o toman el formato que les sea mas util de:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

pero digamos que las promesas en funciones sincronas no son tan utiles para eso esta try catch para validar si algo que deberia estar en el try este ready si no cae al catch esta mal implementada esta clase ya que no explica la realidad de las promesas si nos vamos a principios SOLID los route aplicarlos a lo que indica ya que la mayoria de esa logia debe estar en el controller

Así podrían usar el formato hh:mm:ss dd/mm/yy para ver mejor las fechas.

const date = new Date();
date:
 date.getHours() +
 ":" +
 date.getMinutes() +
 ":" +
 date.getSeconds() +
 " " +
 date.getDate() +
 "/" +
 (date.getMonth() + 1) +
 "/" +
 date.getFullYear().toString().slice(-2),

Este curso es excelente

muy interesante la clase

Ahora viendo que envía la hora y fecha con los mensajes, me parece útil hacerlo también con los errores, para saber en que momento fue que se generaron.

El req.body siempre me daba undefind por mas que le pase correctamente el json en el body. A todo este estaba utilizando Postman para hacer los llamados a la API, pero cuando cambie a insomnia me llegaron correctamente los POST. No se a que se debe esto, pero si alguien quiere probar eso tal vez le sirva

Muy interesante este curso.
Práctica:

Excelente clase Tocayo!!

Tengo una duda. Estuve probando qué sucedería si hubiera un error dentro del método then, por ejemplo procesando la respuesta, y me pareció que podría manejar mejor el flujo de mi programa si manejo la respuesta de la siguiente manera:

controller.addMessage(req.body.user, req.body.message)
    .then(
      resolve => {
        console.log(10/a)  // Error bestial de ejemplo
        response.success(req, res, 201, 'Mensaje creado correctamente')
      },
      error => {
        console.log(10/a) // Error bestial de ejemplo
        response.error(req, res, 400, "Algunos datos pueden estar incompletos", error)
      }
    )
    .catch(e => {
      response.error(req, res, 500, "Error interno del servidor", e)
    })```

Entonces en el caso que tuviera un error dentro de mi resolve o error, especialmente en desarrollo sería más fácil detectarlo (en este ejemplo  console.log(10/a)), y catch me devolvería el error que tuve finalmente, y no le estaría echando la culpa al usuario de haber ingresado datos incorrectos, cuando la culpa fue mía durante el procesamiento de la respuesta.
Si esto es una mala práctica o no fuera necesario me gustaría saber por qué. Muchas gracias.

8:55 — Cuando utilizo Insomnia no me da el mismo resultado. Me dice:

{ "error": "Informacion invalida", "body": "" }

Estoy seguro de tener los códigos bien escritos.

Ayuda, por favor.

Buenas noches, Disculpen tengo un problema al ejecutar el post el cliente RES que estoy usando me retorna este error:
pre>SyntaxError: Unexpected token u in JSON at position 4<br>    at JSON.parse (<anonymous>)<br>    at parse (/home/jorge/Documents/WORKSPACE/nodeJsIni/node_modules/body-parser/lib/types/json.js:89:19)<br>    at /home/jorge/Documents/WORKSPACE/nodeJsIni/node_modules/body-parser/lib/read.js:121:18<br>    at invokeCallback (/home/jorge/Documents/WORKSPACE/nodeJsIni/node_modules/raw-body/index.js:224:16)<br>    at done (/home/jorge/Documents/WORKSPACE/nodeJsIni/node_modules/raw-body/index.js:213:7)<br>    at IncomingMessage.onEnd (/home/jorge/Documents/WORKSPACE/nodeJsIni/node_modules/raw-body/index.js:273:7)<br>    at emitNone (events.js:106:13)<br>    at IncomingMessage.emit (events.js:208:7)<br>    at endReadableNT (_stream_readable.js:1064:12)<br>    at _combinedTickCallback (internal/process/next_tick.js:138:11)</pre>
</body>

Muy buena clase!

Mi promesa no deja de caer en el catch, aunque nunca se ejecuta el reject, ¿a alguien le sucede lo mismo? Se que no cae en el reject porque no se ejecuta el console.error, pero por alguna razón sigue ejecutándose el catch.

Tengo este error, alguien sabe por qué?

El proyecto esta en git?

<h3>He visto que un companiero esta usando TS, y digo ya que lo uso para frontend, por que no para Backend tambien?</h3>

Asi que me he animado hahahah.
Aqui os dejo un video en YT que dice como hacer el Setup:
https://www.youtube.com/watch?v=zRo2tvQpus8

genial la clase!, genial!
Gracias profe!!

Puedes usar el object destructuring, para pasar el user y message de forma mas clara:

router.post('/',(req,res)=>{
    const {body:{user,message}} = req
    controller.addMessage(user, message)
        .then((fullMessage)=>{
            response.success(req,res,200,fullMessage)
        })
        .catch(()=>{
            response.error(req,res,400,'Error')
        })
})

#nuncaparesdeaprender

crear promesa para validar el controlador