анализ ответа JSONP $ http.jsonp () в angular.js

112

Я использую угловой $http.jsonp()запрос, который успешно возвращает json, завернутый в функцию:

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;
    });

Как получить доступ / проанализировать возвращенный JSON, обернутый функцией?

Акронимн
источник
4
С JSONP вы не «получаете доступ / не анализируете возвращаемый JSON, обернутый функцией». Ваш обратный вызов вызван; он получает данные JSON в качестве аргумента.
Мэтт Болл,
Я пробовал делать что-то вроде
akronymn
(извините, нажмите "Enter слишком рано" выше) В какой момент вызывается мой обратный вызов? Фрагмент кода был бы действительно полезен. Я пробовал много разных вещей на этом этапе и был в тупике.
Akronymn
Обратный вызов вызывается, когда возвращается ответ. У вас есть функция с именем jsonp_callback? Если нет, то в этом твоя проблема.
Мэтт Болл,
на данный момент я написал простую функцию, которая просто возвращает первый элемент json, function jsonp_callback(data) { return data.found; //should be 3 }
Akronymn

Ответы:

300

ОБНОВЛЕНИЕ: начиная с Angular 1.6

Вы больше не можете использовать строку JSON_CALLBACK в качестве заполнителя для указания, куда должно идти значение параметра обратного вызова

Теперь вы должны определить обратный вызов следующим образом:

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

Изменить / получить доступ / объявить параметр через $http.defaults.jsonpCallbackParam, по умолчаниюcallback

Примечание. Вы также должны убедиться, что ваш URL-адрес добавлен в надежный / белый список:

$sceDelegateProvider.resourceUrlWhitelist

или явно доверенный через:

$sce.trustAsResourceUrl(url)

success/errorбыли устаревшими .

Эти $httpметоды обещают устаревшие successи errorустарели и будут удалены в v1.6.0. Вместо этого используйте стандартный метод then. Если $httpProvider.useLegacyPromiseExtensionsустановлено, falseто эти методы будут выбрасывать $http/legacy error.

ОБЛАСТЬ ПРИМЕНЕНИЯ:

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);
    });

Предыдущий ответ: Angular 1.5.x и ранее

Все вы должны сделать , это изменить , callback=jsonp_callbackчтобы callback=JSON_CALLBACKвыглядеть примерно так:

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

И тогда ваша .successфункция должна срабатывать, как если бы возврат был успешным.

Поступая таким образом, вы избавляетесь от загрязнения глобального пространства. Это описано в документации AngularJS здесь .

Обновлена ​​скрипка Мэтта Болла для использования этого метода: http://jsfiddle.net/subhaze/a4Rc2/114/

Полный пример:

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
источник
5
мой возвращает другой обратный вызов: angular.callbacks._0, как мне это исправить?
raberana
@ eaon21 у вас есть пример скрипки?
subhaze
2
@ eaon21 это желаемое поведение, angular заменяет JSON_CALLBACK на динамически сгенерированный, вам не нужно обращать на это внимание
Guillaume86
А как например Youtube api вызвать?
Gino
Похоже, у них есть собственная клиентская библиотека для взаимодействия с API. Есть ли у вас примеры, которые помогут сузить круг вопросов, которые вы пытаетесь сделать?
subhaze
69

ГЛАВНОЕ я не понял довольно долго, что запрос должен содержать «обратный вызов = JSON_CALLBACK», потому что AngularJS модифицирует запрос URL , подставляя уникальный идентификатор «JSON_CALLBACK». В ответе сервера должно использоваться значение параметра callback вместо жесткого кодирования JSON_CALLBACK:

JSON_CALLBACK(json_response);  // wrong!

Поскольку я писал свой собственный сценарий PHP-сервера, я думал, что знаю, какое имя функции он хочет, и мне не нужно было передавать в запросе «callback = JSON_CALLBACK». Большая ошибка!

AngularJS заменяет «JSON_CALLBACK» в запросе на уникальное имя функции (например, «callback = angular.callbacks._0»), и ответ сервера должен возвращать это значение:

angular.callbacks._0(json_response);
Джозеф Остер
источник
2
Есть ли способ изменить имя обратного вызова, чтобы он работал с жестко закодированным статическим jsonфайлом.
Павел Николов
9

Это было очень полезно. Angular работает не так, как JQuery. У него есть собственный метод jsonp (), который действительно требует "& callback = JSON_CALLBACK" в конце строки запроса. Вот пример:

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;
    });
});

Затем отобразите или измените {{данные}} в вашем шаблоне Angular.

Питер
источник
4

Это должно сработать для вас, пока функция jsonp_callbackвидна в глобальной области:

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);

Полная демонстрация: http://jsfiddle.net/mattball/a4Rc2/ (отказ от ответственности: я никогда раньше не писал код AngularJS)

Мэтт Болл
источник
Вот и все! Оказывается, прицел я напортачил. Спасибо!
Акронимн
1
Этот ответ не очень помог. Это не соответствует сфере действия AngularJS.
xil3
1
@ xil3 спасибо за отзыв; к сожалению, только OP (akronymn) может переключить принятый ответ, а не я.
Мэтт Болл
@DanieleBrugnara см. Предыдущие комментарии к этому ответу.
Мэтт Болл,
4

Вам все еще нужно указать callbackв параметрах:

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

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

Где «functionName» - это строковая ссылка на глобально определенную функцию. Вы можете определить его вне сценария angular, а затем переопределить в своем модуле.

парадит
источник
2

Для разбора сделайте это -

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

Или вы можете использовать `$ scope.data = JSON.Stringify (data);

В шаблоне Angular вы можете использовать его как

{{data}}
капил
источник
0

для меня вышеуказанные решения работали только после того, как я добавил «format = jsonp» в параметры запроса.

Тали
источник
0

Я использую angular 1.6.4, и ответ, предоставленный subhaze , для меня не сработал. Я немного изменил его, и он сработал - вам нужно использовать значение, возвращаемое $ sce.trustAsResourceUrl . Полный код:

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);
    });
Микатуо
источник