JSONP: El arma secreta del frontend del pasado
\nImagina que eres un desarrollador web en 2010. Necesitas obtener datos de un servidor externo, por ejemplo, el pronóstico del tiempo o el tipo de cambio. Escribes una simple solicitud fetch, pero en la consola del navegador aparece un error rojo: «No 'Access-Control-Allow-Origin' header is present». ¿Te suena familiar?
Esto es la Same-Origin Policy (política del mismo origen) que no permite que tu JavaScript salga del dominio local. Pero, ¿cómo funcionaban entonces los widgets del clima, los botones «Compartir» y los contadores de visitas? La respuesta es simple: usaban JSONP, un truco ingenioso del que hablaremos hoy.
\nEn este artículo responderemos a la popular pregunta de Stack Overflow: «What is JSONP, and why was it created?» — en lenguaje sencillo, con ejemplos de código y sin teoría innecesaria.
\n\n1. El problema: ¿Por qué el navegador bloquea las solicitudes?
\nEl navegador es un paranoico. Protege al usuario de ataques XSS y robo de datos. La Same-Origin Policy permite que JavaScript lea respuestas solo del mismo dominio, protocolo y puerto.
\nEjemplo de bloqueo:
\n// Este código provocará un error CORS\nfetch('https://api.distant-server.com/data')\n .then(response => response.json())\n .then(data => console.log(data));\nPero hay una excepción: las etiquetas <script>. ¡El navegador carga scripts de cualquier dominio sin problemas! Es precisamente esta laguna la que aprovecha JSONP.
\n\n2. La solución: JSONP — JSON con Padding
\nJSONP (JSON with Padding) no es una tecnología ni un formato de datos, sino un patrón (parche) que evita la Same-Origin Policy mediante la etiqueta <script>.
La idea es simple: en lugar de hacer una solicitud a través de XMLHttpRequest, creamos dinámicamente un elemento <script>, especificamos la URL del servidor, y el servidor devuelve no JSON, sino código JavaScript que llama a nuestra función con los datos.
Cómo se ve un JSON normal:
\n// Respuesta del servidor (JSON normal)\n{"name": "PythonLib", "topic": "JSONP"}\n\nCómo se ve JSONP:
\n// Respuesta del servidor (JSONP)\nmyCallback({"name": "PythonLib", "topic": "JSONP"});\nLa diferencia es enorme: en el segundo caso, el servidor envuelve los datos en una llamada a la función myCallback. Eso es precisamente el padding (envoltura).
3. Práctica: Escribiendo una solicitud JSONP manualmente
\nImplementemos un cliente JSONP en JavaScript puro. Esto ayudará a entender la magia.
\n\nfunction jsonp(url, callbackName) {\n // 1. Creamos una función global (callback)\n window[callbackName] = function(data) {\n console.log('Datos recibidos:', data);\n delete window[callbackName]; // Limpiamos\n document.body.removeChild(script);\n };\n\n // 2. Creamos la etiqueta script\n const script = document.createElement('script');\n script.src = `${url}?callback=${callbackName}`; // Pasamos el nombre del callback\n script.onerror = function() {\n console.error('Error al cargar JSONP');\n delete window[callbackName];\n document.body.removeChild(script);\n };\n\n // 3. Lo agregamos al DOM — el navegador carga y ejecuta el script inmediatamente\n document.body.appendChild(script);\n}\n\n// Uso:\njsonp('https://api.example.com/data', 'handleData');\nCómo funciona paso a paso:
\n- \n
- Creamos una función global
handleData. \n - Agregamos la etiqueta
<script>con la URL del servidor. En la URL pasamos el parámetro?callback=handleData. \n - El servidor que soporta JSONP ve el parámetro
callbacky devuelve no JSON, sino JavaScript:handleData({...}). \n - El navegador ejecuta este script, se llama a nuestra función y obtenemos los datos. \n
4. ¿Por qué JSONP es malo? (Desventajas)
\nSi pensaste: «Genial, lo usaré en todas partes»