Alguém pode explicar o que JSONP é, em termos leigos?

Eu sei que JSONP é JSON com preenchimento.

Eu entendo o que é JSON e como usá-lo com jQuery.getJSON() . No entanto, não entendo o conceito do callback de callback ao introduzir o JSONP.

Alguém pode me explicar como isso funciona?

Prefácio:

Esta resposta é mais de seis anos de idade. Embora os conceitos e a aplicação do JSONP não tenham mudado (ou seja, os detalhes da resposta ainda sejam válidos), você deve procurar usar o CORS sempre que possível (ou seja, seu servidor ou API o suporta, e o suporte ao navegador é adequado), como JSONP tem riscos de segurança inerentes .


JSONP ( JSON com Padding ) é um método comumente usado para ignorar as políticas entre domínios em navegadores da web. (Você não tem permissão para fazer solicitações AJAX para uma página da Web que se perceba estar em um servidor diferente pelo navegador.)

JSON e JSONP se comportam de maneira diferente no cliente e no servidor. As solicitações JSONP não são despachadas usando o XMLHTTPRequest e os methods associados do navegador. Em vez disso, uma tag é criada, cuja origem é configurada para o URL de destino. Essa tag de script é então adicionada ao DOM (normalmente dentro do elemento ).

Solicitação JSON:

 var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { // success }; }; xhr.open("GET", "somewhere.php", true); xhr.send(); 

Pedido JSONP:

 var tag = document.createElement("script"); tag.src = 'somewhere_else.php?callback=foo'; document.getElementsByTagName("head")[0].appendChild(tag); 

A diferença entre uma resposta JSON e uma resposta JSONP é que o object de resposta JSONP é passado como um argumento para uma function de retorno de chamada.

JSON:

 { "bar": "baz" } 

JSONP:

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

É por isso que você vê solicitações JSONP contendo o parâmetro de callback , para que o servidor saiba o nome da function para encapsular a resposta.

Essa function deve existir no escopo global no momento em que a tag é avaliada pelo navegador (após a conclusão da solicitação).


Outra diferença a ser percebida entre o tratamento de uma resposta JSON e uma resposta JSONP é que quaisquer erros de análise em uma resposta JSON podem ser capturados envolvendo a tentativa de avaliar o responseText em uma instrução try / catch. Devido à natureza de uma resposta JSONP, os erros de análise na resposta causarão um erro de análise de JavaScript não indexável.

Ambos os formatos podem implementar erros de tempo limite definindo um tempo limite antes de iniciar a solicitação e limpando o tempo limite no manipulador de resposta.


A utilidade de usar o jQuery para fazer solicitações JSONP é que o jQuery faz todo o trabalho para você em segundo plano.

Por padrão, o jQuery requer que você inclua &callback=? na URL do seu pedido AJAX. O jQuery tomará a function de success especificada, atribuirá um nome exclusivo e a publicará no escopo global. Em seguida, ele replaceá o ponto de interrogação ? em &callback=? com o nome que atribuiu.


Implementações JSON / JSONP Comparáveis

O seguinte pressupõe um object de resposta { "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); 

Digamos que você tenha um URL que forneça dados JSON como:

 {'field': 'value'} 

… e você tinha uma URL semelhante, exceto que usava o JSONP, ao qual você passava o nome da function de retorno de chamada ‘myCallback’ (geralmente feito com um parâmetro de consulta chamado ‘callback’, por exemplo, http://example.com/dataSource?callback=myCallback ). Então retornaria:

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

… o que não é apenas um object, mas é na verdade um código que pode ser executado. Portanto, se você definir uma function em outra parte da sua página chamada myFunction e executar esse script, ela será chamada com os dados da URL.

O legal disso é: você pode criar uma tag de script e usar sua URL (completa com o parâmetro callback ) como o atributo src , e o navegador irá executá-la. Isso significa que você pode contornar a política de segurança de “mesma origem” (porque os navegadores permitem que você execute tags de script de fonts diferentes do domínio da página).

Isto é o que o jQuery faz quando você faz um pedido ajax (usando .ajax com ‘jsonp’ como o valor para a propriedade dataType ). Por exemplo

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

Aqui, o jQuery cuida do nome da function de retorno de chamada e do parâmetro de consulta – tornando a API idêntica a outras chamadas do ajax. Mas, ao contrário de outros tipos de solicitações de ajax, como mencionado, você não está restrito a obter dados da mesma origem da sua página.

O JSONP é uma maneira de contornar a política de mesma origem do navegador. Como? Como isso:

insira a descrição da imagem aqui

O objective aqui é fazer uma solicitação para otherdomain.com e alert o nome na resposta. Normalmente, fazemos um pedido AJAX:

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

No entanto, como a solicitação está sendo enviada para um domínio diferente, isso não funcionará.

Podemos fazer o pedido usando uma tag . Ambos e $.get('otherdomain.com') resultarão na mesma solicitação sendo feita:

 GET otherdomain.com 

P: Mas se usarmos a tag , como poderíamos acessar a resposta? Precisamos acessá-lo se quisermos alert lo.

A: Não podemos. Mas aqui está o que poderíamos fazer - definir uma function que usa a resposta e, em seguida, dizer ao servidor para responder com JavaScript que chama nossa function com a resposta como seu argumento.

P: Mas e se o servidor não fizer isso por nós e estiver apenas disposto a retornar o JSON para nós?

A: Então não poderemos usá-lo. O JSONP requer que o servidor coopere.

P: Ter que usar uma tag é feio.

R: Bibliotecas como o jQuery tornam isso mais interessante . Ex:

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

Ele funciona criando dinamicamente o elemento DOM da tag .

P: As tags só fazem solicitações GET - e se quisermos fazer uma solicitação POST?

A: Então o JSONP não funcionará para nós.

P: Tudo bem, só quero fazer uma solicitação GET. JSONP é incrível e eu vou usá-lo - obrigado!

R: Na verdade, não é tão legal assim. É realmente apenas um hack. E não é a coisa mais segura de usar. Agora que o CORS está disponível, você deve usá-lo sempre que possível.

Eu encontrei um artigo útil que também explica o assunto de forma clara e fácil. Link é JSONP

Alguns dos pontos dignos de nota são:

  1. JSONP pré-data CORS.
  2. É uma maneira pseudo-padrão de recuperar dados de um domínio diferente,
  3. Possui resources CORS limitados (somente método GET)

Trabalhar é como segue:

  1. está incluído no código html
  2. Quando o passo 1 é executado, ele detecta uma function com o mesmo nome de function (conforme fornecido no parâmetro url) como uma resposta.
  3. Se a function com o nome dado existir no código, ela será executada com os dados, se houver algum, retornados como um argumento para essa function.