// Reto: crear un wrapper asyncHandler y un middleware de errores centralizado.
// Problema: en Express 4, si un handler async lanza un error (o su promesa se rechaza),
// Express NO lo captura solo. La peticion se queda colgada. El wrapper lo soluciona.
//
// Entrada / salida esperada:
// GET /ok -> 200 { dato: "todo bien" }
// GET /falla -> 500 { error: "Algo salio mal" } (el error se captura y se maneja)
//
// Como probarlo:
// 1. npm install
// 2. node 06-retos-codigo/async-error-handler.js
// 3. curl http://localhost:3000/ok
// curl http://localhost:3000/falla
const express = require("express");
const app = express();
const PORT = process.env.PORT || 3000;
// asyncHandler envuelve un handler async y captura cualquier rechazo,
// pasandolo a next(err). Asi Express puede enrutar el error al middleware
// de errores en lugar de dejar la peticion colgada.
// Promise.resolve(...) normaliza el retorno: funcione o no como promesa,
// .catch atrapa el error y lo reenvia a next.
function asyncHandler(fn) {
return (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
}
// Simula una operacion async que funciona (por ejemplo, leer de una BD).
async function operacionExitosa() {
return { dato: "todo bien" };
}
// Simula una operacion async que falla.
async function operacionQueFalla() {
throw new Error("fallo interno de la operacion");
}
// Ruta OK: sin wrapper tambien funcionaria, pero usamos el mismo patron.
app.get(
"/ok",
asyncHandler(async (req, res) => {
const resultado = await operacionExitosa();
res.status(200).json(resultado);
})
);
// Ruta que falla: gracias al wrapper, el error llega al middleware de errores.
app.get(
"/falla",
asyncHandler(async (req, res) => {
await operacionQueFalla(); // esto lanza; el wrapper lo captura
res.json({ nunca: "se llega aqui" });
})
);
// Middleware de errores CENTRALIZADO. Se reconoce porque tiene 4 parametros:
// (err, req, res, next). Express solo lo llama cuando algo pasa un error a next().
// Va SIEMPRE al final, despues de las rutas.
app.use((err, req, res, next) => {
// En el servidor si registramos el error real para depurar.
console.error("Error capturado:", err.message);
// Al cliente NO le exponemos el stack ni detalles internos: solo un mensaje generico.
res.status(500).json({ error: "Algo salio mal" });
});
app.listen(PORT, () => {
console.log(`Servidor con manejo de errores async en http://localhost:${PORT}`);
});
module.exports = { app, asyncHandler };