¿Alguien puede explicar qué es JSONP, en términos sencillos? [duplicar]

Resuelto Someone asked hace 13 años • 4 respuestas

JSONPque es JSONcon relleno.

Entiendo qué es JSON y cómo usarlo con jQuery.getJSON(). Sin embargo, no entiendo el concepto callbackal presentar JSONP.

¿Alguien puede explicarme cómo funciona esto?

Someone avatar Oct 01 '10 21:10 Someone
Aceptado

Prefacio:

Esta respuesta tiene más de seis años. Si bien los conceptos y la aplicación de JSONP no han cambiado (es decir, los detalles de la respuesta siguen siendo válidos), debe intentar utilizar CORS siempre que sea posible (es decir, su servidor o API lo admite y la compatibilidad del navegador es adecuada), ya que JSONP tiene riesgos de seguridad inherentes .


JSONP ( JSON con relleno ) es un método comúnmente utilizado para eludir las políticas entre dominios en los navegadores web. (No está permitido realizar solicitudes AJAX a una página web que el navegador percibe como en un servidor diferente).

JSON y JSONP se comportan de manera diferente en el cliente y en el servidor. Las solicitudes JSONP no se envían utilizando los XMLHTTPRequestmétodos de navegador asociados. En su lugar, se crea una <script>etiqueta cuyo origen se establece en la URL de destino. Esta etiqueta de script luego se agrega al DOM (normalmente dentro del <head>elemento).

Solicitud JSON:

var xhr = new XMLHttpRequest();

xhr.onreadystatechange = function () {
  if (xhr.readyState == 4 && xhr.status == 200) {
    // success
  };
};

xhr.open("GET", "somewhere.php", true);
xhr.send();

Solicitud JSONP:

var tag = document.createElement("script");
tag.src = 'somewhere_else.php?callback=foo';

document.getElementsByTagName("head")[0].appendChild(tag);

La diferencia entre una respuesta JSON y una respuesta JSONP es que el objeto de respuesta JSONP se pasa como argumento a una función de devolución de llamada.

JSON:

{ "bar": "baz" }

JSONP:

foo( { "bar": "baz" } );

Es por eso que ve solicitudes JSONP que contienen el callbackparámetro, para que el servidor conozca el nombre de la función para envolver la respuesta.

Esta función debe existir en el ámbito global en el momento en que<script> el navegador evalúa la etiqueta (una vez que se ha completado la solicitud).


Otra diferencia a tener en cuenta entre el manejo de una respuesta JSON y una respuesta JSONP es que cualquier error de análisis en una respuesta JSON se puede detectar envolviendo el intento de evaluar el texto de respuesta en una declaración try/catch. Debido a la naturaleza de una respuesta JSONP, los errores de análisis en la respuesta provocarán un error de análisis de JavaScript imposible de detectar.

Ambos formatos pueden implementar errores de tiempo de espera estableciendo un tiempo de espera antes de iniciar la solicitud y borrando el tiempo de espera en el controlador de respuestas.


Usando jQuery

La utilidad de usar jQuery para realizar solicitudes JSONP es que jQuery hace todo el trabajo por usted en segundo plano.

De forma predeterminada, jQuery requiere que lo incluya &callback=?en la URL de su solicitud AJAX. jQuery tomará la successfunción que especifique, le asignará un nombre único y la publicará en el ámbito global. Luego reemplazará el signo de interrogación ?con &callback=?el nombre que le ha asignado.


Implementaciones JSON/JSONP comparables

Lo siguiente supone un objeto de respuesta.{ "bar" : "baz" }

JSON:

var xhr = new XMLHttpRequest();

xhr.onreadystatechange = function () {
  if (xhr.readyState == 4 && xhr.status == 200) {
    document.getElementById("output").innerHTML = eval('(' + this.responseText + ')').bar;
  };
};

xhr.open("GET", "somewhere.php", true);
xhr.send();

JSONP:

function foo(response) {
  document.getElementById("output").innerHTML = response.bar;
};

var tag = document.createElement("script");
tag.src = 'somewhere_else.php?callback=foo';

document.getElementsByTagName("head")[0].appendChild(tag);
Matt avatar Oct 01 '2010 14:10 Matt

Digamos que tienes alguna URL que te proporciona datos JSON como:

{'field': 'value'}

...y tenía una URL similar excepto que usaba JSONP, a la que le pasaba el nombre de la función de devolución de llamada 'myCallback' (generalmente se hace dándole un parámetro de consulta llamado 'devolución de llamada', por ejemplo http://example.com/dataSource?callback=myCallback). Entonces volvería:

myCallback({'field':'value'})

...que no es sólo un objeto, sino que en realidad es un código que se puede ejecutar. Entonces, si define una función en otra parte de su página llamada myFunctiony ejecuta este script, se llamará con los datos de la URL.

Lo bueno de esto es que puedes crear una etiqueta de secuencia de comandos y usar tu URL (completa con callbackel parámetro) como srcatributo, y el navegador la ejecutará. Eso significa que puede eludir la política de seguridad del "mismo origen" (porque los navegadores le permiten ejecutar etiquetas de script desde fuentes distintas al dominio de la página).

Esto es lo que hace jQuery cuando realiza una solicitud ajax (usando .ajax'jsonp' como valor de la dataTypepropiedad). P.ej

$.ajax({
  url: 'http://example.com/datasource',
  dataType: 'jsonp',
  success: function(data) {
    // your code to handle data here
  }
});

Aquí, jQuery se encarga del nombre de la función de devolución de llamada y del parámetro de consulta, lo que hace que la API sea idéntica a otras llamadas ajax. Pero a diferencia de otros tipos de solicitudes ajax, como se mencionó, no está restringido a obtener datos del mismo origen que su página.

sje397 avatar Oct 01 '2010 14:10 sje397

JSONP es una forma de eludir la política del mismo origen del navegador . ¿Cómo? Como esto:

ingrese la descripción de la imagen aquí

El objetivo aquí es hacer una solicitud otherdomain.comy alertel nombre en la respuesta. Normalmente haríamos una solicitud AJAX:

$.get('otherdomain.com', function (response) {
  var name = response.name;
  alert(name);
});

Sin embargo, dado que la solicitud se envía a un dominio diferente, no funcionará.

Sin embargo , podemos realizar la solicitud utilizando una <script>etiqueta. Ambos <script src="otherdomain.com"></script>y $.get('otherdomain.com')darán lugar a que se realice la misma solicitud:

GET otherdomain.com

P: Pero si usamos la <script>etiqueta, ¿cómo podríamos acceder a la respuesta? Necesitamos acceder a él si queremos alert.

R: Uh, no podemos. Pero esto es lo que podríamos hacer: definir una función que use la respuesta y luego decirle al servidor que responda con JavaScript que llame a nuestra función con la respuesta como argumento.

P: ¿Pero qué pasa si el servidor no hace esto por nosotros y solo está dispuesto a devolvernos JSON?

R: Entonces no podremos usarlo. JSONP requiere que el servidor coopere.

P: Tener que usar una <script>etiqueta es feo.

R: Bibliotecas como jQuery lo hacen más agradable . Ex:

$.ajax({
    url: "http://otherdomain.com",
    jsonp: "callback",
    dataType: "jsonp",
    success: function( response ) {
        console.log( response );
    }
});

Funciona creando dinámicamente el <script>elemento DOM de etiqueta.

P: <script>Las etiquetas solo realizan solicitudes GET. ¿Qué sucede si queremos realizar una solicitud POST?

R: Entonces JSONP no funcionará para nosotros.

P: Está bien, solo quiero realizar una solicitud GET. JSONP es increíble y voy a usarlo, ¡gracias!

R: En realidad, no es tan asombroso. Realmente es solo un truco. Y no es lo más seguro de usar. Ahora que CORS está disponible, debes usarlo siempre que sea posible.

Adam Zerner avatar May 07 '2017 18:05 Adam Zerner

Encontré un artículo útil que también explica el tema con bastante claridad y en un lenguaje sencillo. El enlace es JSONP.

Algunos de los puntos dignos de mención son:

  1. JSONP es anterior a CORS.
  2. Es una forma pseudoestándar de recuperar datos de un dominio diferente,
  3. Tiene funciones CORS limitadas (solo método GET)

El funcionamiento es el siguiente:

  1. <script src="url?callback=function_name">está incluido en el código html
  2. Cuando se ejecuta el paso 1, detecta una función con el mismo nombre de función (como se indica en el parámetro URL) como respuesta.
  3. Si la función con el nombre de pila existe en el código, se ejecutará con los datos, si los hay, devueltos como argumento para esa función.
Harshit Garg avatar Jun 29 '2017 02:06 Harshit Garg