JSONP Clarified
JSONP stands for "JSON with padding". JSONP is a means of passing Javascript expressions cross-origin. It is an alternative way to fetch data that can bypass the same-origin policy in a way normal AJAX calls cannot. JSONP allows us quick cross-domain usage of APIs, but has the disadvantage of being unable to perform error checking in older browsers. It also disallows us from making POST request. Only cross domain calls which result with the evaluation of received data using Javascript in the browser require JSONP. Interfaces which implements CORS do not require JSONP. For example, Twitter API and Google Maps API do not require JSONP. Another disadvantage of JSONP is it leaves your application vulnerable to XSS attacks by the foreign origin you are requesting from. If the remote end of the JSONP source isn't trusted, your application is open to an XSS attack.
How to use JSONP
I recently had to use an API in order to retrieve weather data. In doing so I
learned all about the restrictions incurred by the same-origin policy and how to
get around it using JSONP. JSONP allows developers to get around the same-origin
policy. JSONP takes advantage of the fact that the <script>
tag does not need to abide by the same-origin
policy. We can create a <script>
tag and set it's src
attribute to our API endpoint. Additionally, we can even specify options right there in the src
url, such as the return format and the callback to be triggered right there in
the src
attribute.
app.coffee
script = document.createElement("script") script.src = "http://api.worldweatheronline.com/free/v1/weather.ashx?q=#{query}&format=json&callback=processWeather&key=j8xvysb7t9jp2dvw7pwcbgs3" document.body.appendChild(script)
Notice the callback=processWeather
code in the src
attribute. This callback option makes it so when the data is retrived from the
API then that callback is called with the return data. All we need to do is
declare the callback function in app.coffee.
app.coffee
window.processWeather = (weather) -> if weather.data.error #do stuff else #do some other stuff
Nuances of Scoping in CoffeeScript
Notice that I declared processWeather on the window
object. I had to do this
because CoffeeScript wraps all code inside an anonymous function when it
compiles into JavaScript. Since the
src
attribute that is activating processWeather
is calling from outside the
app.coffee scope, processWeather
needs to be declared on the
window object so that it is accessible to the callback.
Using JSONP with AJAX
One way to perform a JSONP request it by using a
<script>
tag with an embedded callback in it and appending it to the DOM.
There exist other ways to perform a JSONP
request. One of those other ways is to use ajax. JSONP can be used in
conjunction with ajax. All you need to
do is create a normal ajax get request and change a few properties of the object
you pass in. On the object you pass into the ajax
method the dataType
property should be set to "jsonp"
and the jsonpCallback
property should be set to whatever callback you want to use on the response
data.
Example
app.coffee
request = (requestType) -> { url: endpointURL requestType jsonpCallback: "displayMovies" dataType: "jsonp" } $(document).ready -> $('#opening').click -> $.ajax request "opening" $('#now').click -> $.ajax request "in_theaters" $('#coming').click -> $.ajax request "upcoming"
And bam! JSONP will work with ajax!