analisando a resposta JSONP $ http.jsonp () no angular.js

112

Estou usando a $http.jsonp()solicitação do angular que está retornando json embrulhado em uma função com sucesso:

var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts?callback=jsonp_callback";

$http.jsonp(url).
    success(function(data, status, headers, config) {
        //what do I do here?
    }).
    error(function(data, status, headers, config) {
        $scope.error = true;
    });

Como acessar / analisar o JSON empacotado com função retornado?

akronymn
fonte
4
Com JSONP você não "acessa / analisa o JSON retornado da função empacotada." Seu retorno de chamada é chamado; ele recebe os dados JSON como um argumento.
Matt Ball
Eu tentei fazer algo como
akronymn em
(desculpe, pressione Enter muito cedo acima) Em que ponto meu retorno de chamada é chamado? Um trecho de código seria muito útil. Eu tentei várias coisas diferentes neste momento e estou perplexo.
akronymn de
O retorno de chamada é chamado quando a resposta retorna. Você tem uma função chamada jsonp_callback? Se não, aí está o seu problema.
Matt Ball
por enquanto, escrevi uma função simples para retornar apenas o primeiro elemento do json, function jsonp_callback(data) { return data.found; //should be 3 }
akronymn

Respostas:

300

ATUALIZAÇÃO: desde Angular 1.6

Você não pode mais usar a string JSON_CALLBACK como um espaço reservado para especificar onde o valor do parâmetro de retorno de chamada deve ir

Agora você deve definir o retorno de chamada assim:

$http.jsonp('some/trusted/url', {jsonpCallbackParam: 'callback'})

Alterar / acessar / declarar parâmetro via $http.defaults.jsonpCallbackParam, o padrão écallback

Observação: você também deve certificar-se de que seu URL seja adicionado à lista de permissões / confiáveis:

$sceDelegateProvider.resourceUrlWhitelist

ou explicitamente confiável via:

$sce.trustAsResourceUrl(url)

success/errorforam descontinuados .

Os $httpmétodos promessa legados successe errortem sido substituído e será removido em v1.6.0. Use o método padrão then. Se $httpProvider.useLegacyPromiseExtensionsfor definido como false, esses métodos irão lançar $http/legacy error.

USAR:

var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts"
var trustedUrl = $sce.trustAsResourceUrl(url);

$http.jsonp(trustedUrl, {jsonpCallbackParam: 'callback'})
    .then(function(data){
        console.log(data.found);
    });

Resposta Anterior: Angular 1.5.x e antes

Tudo que você precisa fazer é mudar callback=jsonp_callbackpara callback=JSON_CALLBACKassim:

var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts?callback=JSON_CALLBACK";

E então sua .successfunção deve disparar como você fez se o retorno foi bem-sucedido.

Fazer isso dessa forma evita que você tenha que sujar o espaço global. Isso está documentado na documentação do AngularJS aqui .

Atualizou o violino de Matt Ball para usar este método: http://jsfiddle.net/subhaze/a4Rc2/114/

Exemplo completo:

var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts?callback=JSON_CALLBACK";

$http.jsonp(url)
    .success(function(data){
        console.log(data.found);
    });
subhaze
fonte
5
o meu está retornando um retorno de chamada diferente: angular.callbacks._0 como devo corrigir isso?
raberana
@ eaon21 você tem um exemplo de violino?
subhaze
2
@ eaon21 é o comportamento desejado, angular substitui JSON_CALLBACK por um gerado dinamicamente, você não precisa prestar atenção a isso
Guillaume86
E como você chama a API do Youtube, por exemplo?
Gino
Parece que eles têm sua própria biblioteca do lado do cliente para interagir com a API. Algum exemplo que possa ajudar a restringir o que você está tentando fazer?
subhaze
69

A COISA MAIS IMPORTANTE que eu não entendi por um bom tempo é que a solicitação DEVE conter "callback = JSON_CALLBACK", porque AngularJS modifica a url da solicitação , substituindo um identificador único por "JSON_CALLBACK". A resposta do servidor deve usar o valor do parâmetro 'callback' em vez do código permanente "JSON_CALLBACK":

JSON_CALLBACK(json_response);  // wrong!

Como estava escrevendo meu próprio script de servidor PHP, pensei que sabia o nome da função que ele queria e não precisava passar "callback = JSON_CALLBACK" na solicitação. Grande erro!

AngularJS substitui "JSON_CALLBACK" na solicitação por um nome de função exclusivo (como "callback = angular.callbacks._0"), e a resposta do servidor deve retornar esse valor:

angular.callbacks._0(json_response);
Joseph Oster
fonte
2
Existe alguma maneira de alterar o nome do retorno de chamada para que funcione com jsonarquivo estático embutido em código .
Pavel Nikolov
9

Isso foi muito útil. Angular não funciona exatamente como JQuery. Ele tem seu próprio método jsonp (), que de fato requer "& callback = JSON_CALLBACK" no final da string de consulta. Aqui está um exemplo:

var librivoxSearch = angular.module('librivoxSearch', []);
librivoxSearch.controller('librivoxSearchController', function ($scope, $http) {
    $http.jsonp('http://librivox.org/api/feed/audiobooks/author/Melville?format=jsonp&callback=JSON_CALLBACK').success(function (data) {
        $scope.data = data;
    });
});

Então exiba ou manipule {{data}} em seu template Angular.

Peter
fonte
4

Isso deve funcionar bem para você, desde que a função jsonp_callbackseja visível no escopo global:

function jsonp_callback(data) {
    // returning from async callbacks is (generally) meaningless
    console.log(data.found);
}

var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts?callback=jsonp_callback";

$http.jsonp(url);

Demonstração completa: http://jsfiddle.net/mattball/a4Rc2/ (isenção de responsabilidade: nunca escrevi nenhum código AngularJS antes)

Matt Ball
fonte
Isso foi o suficiente! Acontece que o escopo que eu estava bagunçando. Obrigado!
akronymn de
1
Essa resposta não foi muito útil. Não segue o escopo do AngularJS.
xil3 de
1
@ xil3 obrigado pelo feedback; infelizmente, apenas o OP (akronymn) pode mudar a resposta aceita, não eu.
Matt Ball de
@DanieleBrugnara, consulte os comentários anteriores a esta resposta.
Matt Ball
4

Você ainda precisa definir callbackos parâmetros:

var params = {
  'a': b,
  'token_auth': TOKEN,
  'callback': 'functionName'
};
$sce.trustAsResourceUrl(url);

$http.jsonp(url, {
  params: params
});

Onde 'functionName' é uma referência stringificada para uma função definida globalmente. Você pode defini-lo fora de seu script angular e redefini-lo em seu módulo.

paradite
fonte
2

Para analisar, faça isso-

   $http.jsonp(url).
    success(function(data, status, headers, config) {
    //what do I do here?
     $scope.data=data;
}).

Ou você pode usar `$ scope.data = JSON.Stringify (data);

No modelo Angular, você pode usá-lo como

{{data}}
Kapil
fonte
0

para mim, as soluções acima funcionaram apenas quando adicionei "format = jsonp" aos parâmetros de solicitação.

Tali
fonte
0

Estou usando o angular 1.6.4 e a resposta fornecida por subhaze não funcionou para mim. Eu modifiquei um pouco e funcionou - você tem que usar o valor retornado por $ sce.trustAsResourceUrl . Código completo:

var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts"
url = $sce.trustAsResourceUrl(url);

$http.jsonp(url, {jsonpCallbackParam: 'callback'})
    .then(function(data){
        console.log(data.found);
    });
Mikatuo
fonte