114

I am using angular's $http.jsonp() request which is successfully returning json wrapped in a function:

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

How to access/parse the returned function-wrapped-JSON?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
akronymn
  • 2,426
  • 4
  • 25
  • 39
  • 4
    With JSONP you don't "access/parse the returned function-wrapped-JSON." Your callback is called; it receives the JSON data as an argument. – Matt Ball Aug 22 '12 at 03:39
  • I've tried doing something like – akronymn Aug 22 '12 at 13:59
  • (sorry hit enter too soon above) At what point is my callback called? A code snippet would be really helpful. I've tried a number of different things at this point and am stumped. – akronymn Aug 22 '12 at 14:21
  • The callback is called when the response comes back. Do you have a function named `jsonp_callback`? If not, there's your problem. – Matt Ball Aug 22 '12 at 14:24
  • for now I've written a simple function to just return the first element of the json, `function jsonp_callback(data) { return data.found; //should be 3 }` – akronymn Aug 22 '12 at 14:32
  • To people reading this question: Check out the solution to this problem that has been posted *RIGHT AFTER* the accepted answer. – Mr_Pouet Mar 06 '14 at 04:34

8 Answers8

302

UPDATE: since Angular 1.6

You can no longer use the JSON_CALLBACK string as a placeholder for specifying where the callback parameter value should go

You must now define the callback like so:

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

Change/access/declare param via $http.defaults.jsonpCallbackParam, defaults to callback

Note: You must also make sure your URL is added to the trusted/whitelist:

$sceDelegateProvider.resourceUrlWhitelist

or explicitly trusted via:

$sce.trustAsResourceUrl(url)

success/error were deprecated.

The $http legacy promise methods success and error have been deprecated and will be removed in v1.6.0. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.

USE:

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

Previous Answer: Angular 1.5.x and before

All you should have to do is change callback=jsonp_callback to callback=JSON_CALLBACK like so:

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

And then your .success function should fire like you have it if the return was successful.

Doing it this way keeps you from having to dirty up the global space. This is documented in the AngularJS documentation here.

Updated Matt Ball's fiddle to use this method: http://jsfiddle.net/subhaze/a4Rc2/114/

Full example:

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
  • 8,815
  • 2
  • 30
  • 33
  • 5
    mine is returning a different callback: angular.callbacks._0 how should i fix this? – raberana Jul 13 '13 at 05:09
  • @eaon21 do you have a fiddle example? – subhaze Jul 14 '13 at 02:50
  • 2
    @eaon21 it's the desired behavior, angular substitutes JSON_CALLBACK to a dynamicly generated one, you don't have to pay attention to it – Guillaume86 Feb 13 '14 at 20:04
  • And how do you call Youtube api for example? – Gino Mar 14 '17 at 00:17
  • It appears they have their own client side lib for interacting with the API. Any examples you have that can help narrow down what you're trying to do? – subhaze Mar 14 '17 at 17:42
  • regarding the `Angular 1.6` example - `success` is also deprecated.. you should use `then` – Kunal Dec 22 '17 at 23:05
  • @Kunal thanks for the heads up! I've updated the answer to include this info. – subhaze Dec 23 '17 at 23:45
  • @subhaze This is not working for me, I am using AngularJS 1.6, I tried all the above steps with AngularJS 1.5 also, can you have a look at this plunk. https://plnkr.co/edit/uOptrjxaFhT7xeaHX8YR?p=preview – Swapnil Mar 19 '18 at 16:40
  • Could just be that you're requesting http on a secured connection. Try `https` instead of `http` for your API endpoint if it supports it. – subhaze Mar 22 '18 at 15:43
  • Hmm... just tried https myself and it doesn't appear to support `https` https://starlord.hackerearth.com/hackernews?callback=angular.callbacks._0 so it probably wont work on any URL that's `https`. I also noticed on the non https side `http://starlord.hackerearth.com/hackernews?callback=angular.callbacks._0` it's not sending back JSONP, it's just sending back JSON – subhaze Mar 22 '18 at 15:46
69

The MOST IMPORTANT THING I didn't understand for quite awhile is that the request MUST contain "callback=JSON_CALLBACK", because AngularJS modifies the request url, substituting a unique identifier for "JSON_CALLBACK". The server response must use the value of the 'callback' parameter instead of hard coding "JSON_CALLBACK":

JSON_CALLBACK(json_response);  // wrong!

Since I was writing my own PHP server script, I thought I knew what function name it wanted and didn't need to pass "callback=JSON_CALLBACK" in the request. Big mistake!

AngularJS replaces "JSON_CALLBACK" in the request with a unique function name (like "callback=angular.callbacks._0"), and the server response must return that value:

angular.callbacks._0(json_response);
Joseph Oster
  • 5,507
  • 1
  • 20
  • 11
9

This was very helpful. Angular doesn't work exactly like JQuery. It has its own jsonp() method, which indeed requires "&callback=JSON_CALLBACK" at the end of the query string. Here's an example:

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

Then display or manipulate {{ data }} in your Angular template.

Peter
  • 383
  • 4
  • 8
4

This should work just fine for you, so long as the function jsonp_callback is visible in the global scope:

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

Full demo: http://jsfiddle.net/mattball/a4Rc2/ (disclaimer: I've never written any AngularJS code before)

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
4

You still need to set callback in the params:

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

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

Where 'functionName' is a stringified reference to globally defined function. You can define it outside of your angular script and then redefine it in your module.

inorganik
  • 24,255
  • 17
  • 90
  • 114
paradite
  • 6,238
  • 3
  • 40
  • 58
2

For parsing do this-

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

Or you can use `$scope.data=JSON.Stringify(data);

In Angular template you can use it as

{{data}}
kapil
  • 1,710
  • 1
  • 15
  • 12
0

for me the above solutions worked only once i added "format=jsonp" to the request parameters.

Tali
  • 37
  • 5
0

I'm using angular 1.6.4 and answer provided by subhaze didn't work for me. I modified it a bit and then it worked - you have to use value returned by $sce.trustAsResourceUrl. Full code:

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
  • 758
  • 6
  • 10