196

Please could someone help me work out how to get started with JSONP?

Code:

$('document').ready(function() {
    var pm_url = 'http://twitter.com/status';
    pm_url += '/user_timeline/stephenfry.json';
    pm_url += '?count=10&callback=photos';
    var photos = function (data) {
     alert(data);
    };
    $.ajax({
        url: pm_url,
        dataType: 'jsonp',
        jsonpCallback: 'photos',
        jsonp: false,
    });
});

Fiddle: http://jsfiddle.net/R7EPt/6/

Should produce an alert, as far as I can work out from the documentation: isn't (but isn't producing any errors either).

thanks.

simon
  • 5,987
  • 13
  • 31
  • 28
  • $.ajax({ url: pm_url, dataType: 'jsonp', jsonpCallback: photos, jsonp: false, }); You had entered photos as a string. – wOlVeRiNe Feb 17 '14 at 10:22

4 Answers4

399

JSONP is really a simply trick to overcome XMLHttpRequest same domain policy. (As you know one cannot send AJAX (XMLHttpRequest) request to a different domain.)

So - instead of using XMLHttpRequest we have to use script HTMLl tags, the ones you usually use to load JS files, in order for JS to get data from another domain. Sounds weird?

Thing is - turns out script tags can be used in a fashion similar to XMLHttpRequest! Check this out:

script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://www.someWebApiServer.com/some-data";

You will end up with a script segment that looks like this after it loads the data:

<script>
{['some string 1', 'some data', 'whatever data']}
</script>

However this is a bit inconvenient, because we have to fetch this array from script tag. So JSONP creators decided that this will work better (and it is):

script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://www.someWebApiServer.com/some-data?callback=my_callback";

Notice my_callback function over there? So - when JSONP server receives your request and finds callback parameter - instead of returning plain JS array it'll return this:

my_callback({['some string 1', 'some data', 'whatever data']});

See where the profit is: now we get automatic callback (my_callback) that'll be triggered once we get the data. That's all there is to know about JSONP: it's a callback and script tags.


NOTE:
These are simple examples of JSONP usage, these are not production ready scripts.

RAW JavaScript demonstration (simple Twitter feed using JSONP):

<html>
    <head>
    </head>
    <body>
        <div id = 'twitterFeed'></div>
        <script>
        function myCallback(dataWeGotViaJsonp){
            var text = '';
            var len = dataWeGotViaJsonp.length;
            for(var i=0;i<len;i++){
                twitterEntry = dataWeGotViaJsonp[i];
                text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
            }
            document.getElementById('twitterFeed').innerHTML = text;
        }
        </script>
        <script type="text/javascript" src="http://twitter.com/status/user_timeline/padraicb.json?count=10&callback=myCallback"></script>
    </body>
</html>


Basic jQuery example (simple Twitter feed using JSONP):

<html>
    <head>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
        <script>
            $(document).ready(function(){
                $.ajax({
                    url: 'http://twitter.com/status/user_timeline/padraicb.json?count=10',
                    dataType: 'jsonp',
                    success: function(dataWeGotViaJsonp){
                        var text = '';
                        var len = dataWeGotViaJsonp.length;
                        for(var i=0;i<len;i++){
                            twitterEntry = dataWeGotViaJsonp[i];
                            text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
                        }
                        $('#twitterFeed').html(text);
                    }
                });
            })
        </script>
    </head>
    <body>
        <div id = 'twitterFeed'></div>
    </body>
</html>


JSONP stands for JSON with Padding. (very poorly named technique as it really has nothing to do with what most people would think of as “padding”.)

JFK
  • 40,963
  • 31
  • 133
  • 306
ThatGuy
  • 14,941
  • 2
  • 29
  • 26
  • 3
    This answer is now somewhat out of date because browsers now support `Access-Control-Allow-Origin` headers which allow regular Ajax calls to be made to some cross-origin domains. – jfriend00 Mar 13 '15 at 02:41
  • 2
    Keep in mind you cannot do a form POST with JSONP. More info here: http://www.markhneedham.com/blog/2009/08/27/jquery-post-jsonp-and-cross-domain-requests/ – thdoan Apr 20 '15 at 03:40
  • 4
    What do you have to consider if you want to make these scripts production-ready? – guest Jul 02 '15 at 22:10
  • 1
    Wow, This is really helpful ! I finally get to know what exactly is JSONP and how does it work! – Jerry Liu Nov 05 '15 at 11:40
150

There is even easier way how to work with JSONP using jQuery

$.getJSON("http://example.com/something.json?callback=?", function(result){
   //response data are now in the result variable
   alert(result);
});

The ? on the end of the URL tells jQuery that it is a JSONP request instead of JSON. jQuery registers and calls the callback function automatically.

For more detail refer to the jQuery.getJSON documentation.

Petr Peller
  • 8,581
  • 10
  • 49
  • 66
  • 2
    @PetrPeller, Seems great but I don't seem to make a product out of it. Can you once see this? [JSFiddle](http://jsfiddle.net/Az9SS/) It alerts no data. Maybe I missed something – tika Jul 18 '14 at 17:32
  • @xDNP JSONP response must be supported by the server. Your sever does not seem to support it as I cannot see any added callback here: http://mylivecanvas.com/api/get_routes.php?date=2071-04-02&callback=test. Also you should use `&callback=?` as it's not the first parameter in your case. – Petr Peller Jul 19 '14 at 14:34
  • 2
    @PetrPeller I am greatly interested on your solution. But, that does not work on me. I don't want to post a new question but it does not help me. What does **does not seem to support by server** mean? What should I do? And can you give me a complete URL that works for my server? I would be grateful on you. _Do I need any server configuration?_ – tika Jul 20 '14 at 10:43
  • @xDNP The server needs to respond with a specifically prepared response for JSONP. (Wrapping the response in a function call). I suggest reading about JSONP before continuing http://en.wikipedia.org/wiki/JSONP – Petr Peller Jul 20 '14 at 12:19
  • NICE! Very nice. I wasn't aware of this convention. – Moby's Stunt Double Mar 04 '16 at 17:40
  • Why are you recommending not to use jQuery? – Jesus H Oct 24 '17 at 00:32
  • @JesusH You definitely can still use it for small and simple sites, but it does not offer tools for more complex single page applications. – Petr Peller Oct 25 '17 at 09:35
  • 3
    What does the last edit, "Please don't use jQuery anymore!" mean? – ParkCheolu Nov 09 '17 at 00:32
  • 1
    It's now 2018, and I'm not sure what is supposed to even be used in 2017! – Vasily Hall Jan 27 '18 at 16:51
  • Think the Edit should be taken out, there's no restriction on JQuery unless it causes issues for your scenario. – Raptus Jul 10 '18 at 12:59
  • Using this technique I get a syntax error in Chrome console; additionally, looking at Network tab I see something strange: http://haya2now.jp/data/data.json?callback=jQuery1112017994359455628528_1543399440567&_=1543399440568 The numbers change at each call; the shorter ones are just unix timestamps, but what about the longest one? Anyway, can this technique be used without knowing how the server is configured? – jumpjack Nov 28 '18 at 10:06
30

In response to the OP, there are two problems with your code: you need to set jsonp='callback', and adding in a callback function in a variable like you did does not seem to work.

Update: when I wrote this the Twitter API was just open, but they changed it and it now requires authentication. I changed the second example to a working (2014Q1) example, but now using github.

This does not work any more - as an exercise, see if you can replace it with the Github API:

$('document').ready(function() {
    var pm_url = 'http://twitter.com/status';
    pm_url += '/user_timeline/stephenfry.json';
    pm_url += '?count=10&callback=photos';
    $.ajax({
        url: pm_url,
        dataType: 'jsonp',
        jsonpCallback: 'photos',
        jsonp: 'callback',
    });
});
function photos (data) {
    alert(data);
    console.log(data);
};

although alert()ing an array like that does not really work well... The "Net" tab in Firebug will show you the JSON properly. Another handy trick is doing

alert(JSON.stringify(data));

You can also use the jQuery.getJSON method. Here's a complete html example that gets a list of "gists" from github. This way it creates a randomly named callback function for you, that's the final "callback=?" in the url.

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>JQuery (cross-domain) JSONP Twitter example</title>
        <script type="text/javascript"src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
        <script>
            $(document).ready(function(){
                $.getJSON('https://api.github.com/gists?callback=?', function(response){
                    $.each(response.data, function(i, gist){
                        $('#gists').append('<li>' + gist.user.login + " (<a href='" + gist.html_url + "'>" + 
                            (gist.description == "" ? "undescribed" : gist.description) + '</a>)</li>');
                    });
                });
            });
        </script>
    </head>
    <body>
        <ul id="gists"></ul>
    </body>
</html>
PapaFreud
  • 3,636
  • 4
  • 34
  • 45
3
<!DOCTYPE html>
<html>
<head>
<style>img{ height: 100px; float: left; }</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<title>An JSONP example </title>
</head>
<body>
<!-- DIV FOR SHOWING IMAGES -->
<div id="images">
</div>
<!-- SCRIPT FOR GETTING IMAGES FROM FLICKER.COM USING JSONP -->
<script>
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?",
{
  format: "json"
},
//RETURNED RESPONSE DATA IS LOOPED AND ONLY IMAGE IS APPENDED TO IMAGE DIV
function(data) {
  $.each(data.items, function(i,item){
  $("<img/>").attr("src", item.media.m).appendTo("#images");

 });
});</script>
</body>
</html> 

The above code helps in getting images from the Flicker API. This uses the GET method for getting images using JSONP. It can be found in detail in here

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Ganesh Babu
  • 3,590
  • 11
  • 34
  • 67