JSONP With Only Native JavaScript – Part I

JSON

JavaScript LogoMost front-end developers consume JSON at some point. It has become commonplace nowadays to fetch data from a cross-domain site and present that data in your page. JSON is lightweight, easy to consume and one of the best things to come along in a while.

Another one of the best things to come along has been this:

jQuery.getJSON()

jQuery makes fetching JSON trivial. And there ain’t nothin’ wrong with that. But it’s not a bad idea to have a solid understanding of exactly what is going on under the hood.

The big advantage of JSONP is that it allows data to be retrieved from any URL on the planet with no concern for the kind of cross-domain limitations of AJAX. So this means that we are taking advantage of one of the older features of the JavaScript language: the ability to inject a remote script into our page. In a nutshell, JSONP is accomplished via dynamic script injection. In other words, you create a script tag, set the ‘src’ attribute to be any script you like, and that script calls a function in your page, passing it some data.

Now in the real world, your remote script would likely be produced by an API that supports JSONP. In these cases you have probably seen the URL of JSONP call look something like this:

http://www.somedomain.com?callback=

This is a more sophisticated approach and will be covered in Part II. For now, however, we will keep things very simple. In order to do so, we have to have an agreement between our JSON file and our web page. Our web page has a function expression that makes that function available, and the JSON file knows to call that function.

First, let’s take a look at our JSON file.

Example # 1

Example # 1 is our JSON file. It is really just a JavaScript file. It consists of one function call: jsonpCallback(). The sole argument to this function call is an array of objects. Each object has two properties: ‘name’ and ‘accountNumber’.

We’ll come back to this file shortly. For now, it’s just important to focus on the fact that this is simply a JavaScript file that makes a function call, and passes an array to that function.

Example # 2

In Example # 2, we have the markup for our web page. Now there are two things happening here:

1) The function declaration jsonpCallback() might look familiar to you. This is the function that is called from our JavaScript file ‘data.js’. Notice that this function takes one argument: ‘data’. So it expects to receive some data. Inside the function we assume that the data came through and we inspect it in the console.

2) After the function declaration, we dynamically append a script to the head of the document. Now if you take a close look at the ‘src’ attribute of our script, you’ll see that it is ‘data.js’

Putting the pieces together

Now that we have the details laid out, let’s walk through the sequence of events:

  1. The page loads, and the function declaration for jsonpCallback() is evaluated
  2. jsonpCallback() now exists and can be called
  3. We dynamically append a script tag to the page
  4. The URL for this new script tag is data.js
  5. data.js is loaded and the code inside of it executed
  6. data.js calls the function jsonpCallback(), and passes it the array of data
  7. jsonpCallback() receives the data passed to it and we inspect it in the console

Again, this is an extremely rudimentary example. The focus here was to illustrate the core concepts in play: dynamic script injection and passing data to a function. In Part II, we will look at a more dynamic approach to JSONP.

Here is a link to the working example for this argument: http://examples.kevinchisholm.com/javascript/jsonp/example-1/

Summary

In this article we learned how to implement JSONP using only native JavaScript. We discussed how the script that we dynamically inject into the page calls a function, passing data into the function that it calls.

Helpful Links for JSONP

http://en.wikipedia.org/wiki/JSONP

http://json-p.org/

http://remysharp.com/2007/10/08/what-is-jsonp/

Making JSONP Calls from HTML5 Web Workers

HTML5

HTML5 LogoThe importScripts() function can be used to load any JavaScript file asynchronously from within a Web Worker, making JSONP a snap.

I just put the finishing touches on a photo gallery for a fairly large commercial web site. This template involved two dependencies: mustache.js and a jQuery carousel plugin, as well as three JSONP calls. All of this has to happen before anything can be displayed in the browser. Fun stuff.

I’ve spent plenty of time pressing F5 over and over to see how many milliseconds I could shave off the page load time. Since there is a bit of data crunching that also has to happen once all dependencies and JSONP calls have loaded, I started to think that this project would be a perfect candidate for some Web Worker love (of course with a safety net for older browsers). After some A/B testing, I could see that there was no real savings when implementing Web Workers. This is because the average 3-second load time was mostly due to the multiple asynchronous calls, not the data crunching. Since asynchronous calls are asynchronous, they don’t lock-up the browser, and it is only their latency that “keeps us waiting.”

That said, in the process of setting up my A/B testing, I had fun messing with Web Workers, and picked up a few new tricks, so I thought I’d post an article about making JSONP calls from a Web Worker.

If you’re not too familiar with HTML5 Web Workers, you might want to read these three posts; they offer an overview and a quick dive in to the topic:

Getting Started with HTML5 Web Workers – Part I
Getting Started with HTML5 Web Workers – Part II
Getting Started with HTML5 Web Workers – Part III

Before diving into the Web Worker code, I’ll just mention that the JSONP call we make responds pretty quickly, almost too quickly. As a result, it’s tough to demo our Web Worker, because there is no sense of “wait” (I spent over an hour making a pretty “loading” experience that merely flickers for a nanosecond because the JSONP call returns so quickly : – ). So I’ve implemented a “sleep” feature: we add &sleep=NUMBER to the query string. This way, we can make the JSONP call perform a little slowly, which helps to demonstrate our topic. Here is the PHP code that is added to the top of the JSONP file:

Ok, a little JSONP / Web Worker Action Please!

Example # 1

In Example # 1, we have the code for our Web Worker. First, there is the JSONP callback. In this callback, we fire off a message to the script that started the worker, and pass it the JSON data. Note that we need to use JSON.stringify() to convert that JSON data to a string. This is because we can only pass strings as messages to and from a Web Worker. But if we “stringify” a JSON object, that will do just fine.

Next we have set up an event listener. When the calling script sends a message to this Worker, the code inside of the event listener is executed. We create a random integer which is used to tell the JSON page to “sleep” for a few seconds, imitating a slow response. The other random # is used as a cache buster.

After that, we simply make the JSONP call. The importScripts() is oh-so-lovely and makes it super easy to import any JavaScript file.

Example # 2

In Example # 2, we have a simplified version of the click handler for the “Make JSONP Call” button. It simply sends a message to the Worker, which “starts” it.

Example # 3

In Example # 3, we instantiate the Worker() constructor, and then set up the event listener for that Worker. The code inside of this event listener will be executed when the Worker sends this script a message. I won’t drive you nuts by going through it line-by-line, but on a high level, we take the JSON data that the Worker sends us, and use JSON.parse() to turn it back into an object. Then, leveraging Mustache.js, we create an unordered list, using the JSON data that the Worker fetched for us.

Here is a link to the full working example for this article. Make sure you click the “Make JSONP Call” button: http://examples.kevinchisholm.com/javascript/web-workers/jsonp/

Summary

Again, the very act of making an asynchronous script call is not so strenuous for the browser. But I can imagine a case in which you need to fetch some JSON and then crunch the return data before passing it to the calling script. In such a case, the “crunching” is what could bog down the browser. And since data you pass to a Web Worker is essentially “copied,” your script could wind up using more memory than necessary, by getting the JSON data, passing a copy of it to the Web Worker, and then getting a copy back from the Worker once it has finished doing some work on the data. That is three copies of the same chunk of data!

By initiating your JSONP call from the Web Worker, you get the data, crunch the data, and then pass the data to the calling script. This removes one “copy” from the whole scenario. And, I’m thinking that after sending the data from the Worker to the calling script, you could probably delete the data inside of the Worker, freeing-memory. Although it will probably get cleaned up by garbage collection. More fun stuff to investigate.

Happy Web Worker-ing!

Kevin

Helpful Links for Web Workers

http://www.sitepoint.com/javascript-threading-html5-web-workers/

http://www.storminthecastle.com/2013/04/19/make-your-ui-more-responsive-with-html5-web-workers/

http://www.codediesel.com/javascript/introducing-html5-web-workers/

http://refcardz.dzone.com/refcardz/html5-web-workers

http://www.tutorialspoint.com/html5/html5_web_workers.htm

Complex Multiple Script Loading Using the jQuery.when() Method and the jQuery.Deferred Object — Part II

jQuery

jQuery LogoWhat happens when your JavaScript code depends on not only multiple asynchronous scripts, but also one or more JSONP calls? Once again, jQuery.Deferred() and jQuery.when() save the day.

In Part I of this article: “Complex Multiple Script Loading Using the jQuery.when() Method and the jQuery.Deferred Object Part I“, we discussed the complex nature of multiple asynchronous dependencies. In that article, we were able to count on jQuery.when() to pay attention to the resolution of our jQuery.Deferred objects. In this second part, we’ll complicate things even further by adding a JSONP dependency. The “complication” is the fact that the success of the JSONP call requires us to re-think how we will leverage our jQuery.Deferred object’s resolution.

In my opinion, the asynchronous script calls are fairly easy to manage:

But what about a JSONP call? How do we squeeze that scenario into the jQuery.Deferred / jQuery.when() paradigm?

The approach I have taken starts with a variable that is set to an unresolved jQuery.Deferred object. As soon as you create this variable, you can then program around it. In the true spirit of JSONP, you can name your callback whatever you want. If the server supports JSONP, then you can assume that it will call your callback, passing in the much-desired return data.

Here is a pseudo-code walk-through:

Example # 1

In Example # 1, we have the core code that makes this all work. The interesting thing is that the actual JSONP call comes last. What we do beforehand is set up the tools we need to handle this asynchronous event. What makes this scenario a bit special is that you manually resolve the jQuery.Deferred object in the JSONP callback: “foo.resolve()”. This very nicely kicks in the .when() method that is chained to the return value of the jQuery.when() call.

Example # 2

In Example # 2, we have the code for the full working example. It builds upon the full working example from Part I of this article, but the added functionality has no connection to the form validation. The point that is (hopefully) being made here is:

  • This code provides a way to ensure that multiple asynchronously loaded dependencies are loaded before further action is taken.
  • This code checks to see if any of the asynchronously loaded dependencies have already been loaded in the page (possibly by hard-coded synchronous calls or another script).
  • This code allows for the inclusion of an asynchronously loaded JSONP dependency.

Going through the code line-by-line would be repetitive as that was already done in Part I. What might be helpful is to look at the code and see where the approach taken in Example # 1 has been worked into the full working code (Example # 2).

Here is the URL for the full working example: http://examples.kevinchisholm.com/jquery/deferred-and-when/complex-multi-async-dependencies.html

Summary

In this article we learned how to accommodate a JSONP call as an asynchronous dependency. We leveraged the jQuery.Deferred object and the jQuery.when() method to manage and act upon the resolution of the JSONP call.

Problems Making JSONP Calls in JSFiddle – PROBLEM SOLVED

JavaScript

JS Fiddle LogoAll the JavaScript you write in the JSFiddle “JavaScript” box gets wrapped in an anonymous function and assigned to the window.onload event of an iframe that is shown when you click the “Run” button.

Last week I published this post: Problems Making JSONP Calls in JSFiddle 

As I was testing out some code, I noticed that JSONP calls were failing when using JsFiddle.net. I took a look at it and just found the answer. It wasn’t too big a deal, just needed to understand how JsFiddle executes the JavaScript code that you put in the lower-left-hand box (i.e. the “JavaScript” box).

Here is the code I testing, that was failing:

In this code, I use the “var” keyword to declare “myCallback” as a function expression, just like I was told in JavaScript summer camp back in the 70s. But even when using the “var” keyword, any variable declared in the global scope becomes a property of the window object. Anyhooo, I confidently assumed that my variable “myCallback” (or window.myCallback) would be available to the script that is loaded by the JSONP call. But that code failed and the following message appeared in the console: “myCallback is not defined”. Bummer.

Well, after a few minutes poking around in Google Chrome Web Inspector, I found the issue:

As I had suspected, JsFiddle executes your JavaScript code in an iframe. What I did not realize at first, is that it wraps all of that code in an anonymous function, that is assigned to the window.onload event. So by using the “var” keyword, my “myCallback” variable became private to the anonymous function. Here is the code that is actually executed by JsFiddle when I clicked “run”:

As a result, my “myCallback” variable (i.e. the function expression) is private, and not available to the outside world.

The answer was simple. I just had to force my “myCallback” variable to be global by removing the “var” keyword:

 

This forces “myCallback” to be an implied global, which in-fact becomes a property of the window object. It’s the exact same thing as if I had written: “window.myCallback – function()….”

Here is the JsFiddle.net link for the code that fails: http://jsfiddle.net/DQHax/

Here is the JsFiddle.net link for the fixed code: http://jsfiddle.net/DQHax/1/

Same thing, only let’s avoid implied globals, and explicitly attach “myCallback” to the window object: http://jsfiddle.net/DQHax/2/

Again, no big deal. But if you found yourself pulling your hair out and were googling for an answer, hopefully I saved you a few strands of hair.

: – )

Kevin

 

 

 

Problems Making JSONP Calls in JSFiddle

JSON

JSFiddle Logo
If you are pulling your hair out while trying to demo a JSONP call with JSFiddle, don’t bother. It won’t work out of the box.

There is no doubt that JSFiddle is a super-useful tool for saving little demos that you can share with others.  I use it like crazy when providing simple demos in this blog. Tons of cool features and in general, a brilliant idea.

One little quirk I ran into this morning is JSONP calls. I’m writing Part II of a post called: “Complex Multiple Script Loading Using the jQuery.when() Method and the jQuery.Deferred Object”. In this second part, I introduce the tricky scenario of adding a JSONP call as a dependency, which is in addition to other dependencies that are multiple asynchronous  JavaScript calls that may (or may not) have already loaded in the page (I know, I know….. I need to get a life).

Anyhooooo….

When attempting the code in example # 1, I got the following error: “myCallback is not defined”.

Example # 1

My guess is that JSFiddle uses iframes to render your test code. I’ve not made any attempt to look into this further, and I’m sure the answer is likely a call to “parent” or something similar. But just in you are pulling your hair out trying to demo a JSONP call using JSFiddle, hopefully this will save you the 20 minutes of troubleshooting that I just did. It won’t work out of the box (again, probably due to the use of iFrames). When I figure out the answer, I will post it. I’ll try to look into it this weekend.

Kevin