Cliente HTTP en JavaScript: haciendo solicitudes correctamente — de la A a la Z
\nEn el desarrollo web moderno, la interacción con APIs externas y servidores es una tarea rutinaria pero críticamente importante. Independientemente de si estás escribiendo un microservicio en Node.js, parseando datos o creando un bot, necesitarás un cliente HTTP confiable. En este artículo analizaremos cómo hacer solicitudes HTTP en JavaScript (Node.js) correctamente, revisaremos bibliotecas populares, manejo de errores, tiempos de espera y mejores prácticas.
\n\n1. Herramientas integradas: módulo http y node-fetch
\nNode.js tiene los módulos integrados http y https, pero su API es de bajo nivel e incómoda para el uso diario. Por lo tanto, a menudo se utilizan bibliotecas envolventes.
1.1. node-fetch (v3+)
\nA partir de la versión 18, Node.js tiene soporte integrado para fetch (experimental). Para versiones anteriores o funcionalidad extendida, usa el paquete node-fetch.
// Instalación: npm install node-fetch\nimport fetch from 'node-fetch';\n\nasync function getUsers() {\n try {\n const response = await fetch('https://jsonplaceholder.typicode.com/users');\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error('Error de solicitud:', error.message);\n }\n}\n\ngetUsers();\n\n1.2. fetch integrado (Node.js 18+)
\nSe usa de manera similar al fetch del navegador:
\n// Node.js 18+ sin paquetes adicionales\nasync function postData() {\n const response = await fetch('https://api.example.com/data', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ key: 'value' })\n });\n return response.json();\n}\n\n2. Axios — el estándar de oro de los clientes HTTP
\nAxios es la biblioteca más popular para solicitudes HTTP en JavaScript. Proporciona una interfaz conveniente, soporte para promesas, interceptores (interceptors) y transformación automática de JSON.
\n\n2.1. Instalación y solicitud GET básica
\n// npm install axios\nconst axios = require('axios');\n\nasync function fetchUsers() {\n try {\n const response = await axios.get('https://jsonplaceholder.typicode.com/users');\n console.log(response.data); // datos ya parseados\n } catch (error) {\n console.error('Error:', error.message);\n }\n}\n\n2.2. Solicitud POST con datos
\nasync function createUser() {\n const newUser = { name: 'Iván', email: 'ivan@example.com' };\n const response = await axios.post('https://jsonplaceholder.typicode.com/users', newUser);\n console.log('Usuario creado:', response.data);\n}\n\n2.3. Configuración de tiempo de espera y encabezados
\nEl tiempo de espera es una opción críticamente importante para evitar que la aplicación se congele:
\nasync function fetchWithTimeout() {\n try {\n const response = await axios.get('https://slow-api.example.com/data', {\n timeout: 5000, // 5 segundos\n headers: {\n 'Authorization': 'Bearer token123',\n 'Accept': 'application/json'\n }\n });\n return response.data;\n } catch (error) {\n if (error.code === 'ECONNABORTED') {\n console.error('Tiempo de espera de la solicitud agotado');\n }\n }\n}\n\n3. Técnicas avanzadas y mejores prácticas
\n\n3.1. Manejo de errores y reintentos (retry)
\nLas redes son inestables, por lo que es importante implementar un mecanismo de reintentos:
\nasync function fetchWithRetry(url, retries = 3) {\n for (let i = 0; i < retries; i++) {\n try {\n const response = await axios.get(url);\n return response.data;\n } catch (error) {\n if (i === retries - 1) throw error; // último intento\n console.log(`Intento ${i + 1} falló, reintentando en ${(i + 1) * 1000}ms...`);\n await new Promise(