| By Nicholas Schlueter | Article Rating: |
|
| February 23, 2007 09:30 PM EST | Reads: |
7,445 |
I am a developer rather than a writer or great thinker or futurist. But I think it's obvious that JavaScript APIs will give access to more and more data. I was critical of some of Google’s decisions in their AJAX Search API, but despite my nitpicking they are exposing their entire database and it couldn’t be easier to use. Obviously, they couldn’t send you their entire database, instead they send you a small amount of JS to get you started. Then when you ask for more, they happily send what you ask for.
But Google wants to make sure you aren’t greedy. By making the API JS it helps them protect their data. It seems counterintuitive at first. A typical REST or SOAP api is very easy to harvest, because once you have the client built you can just write a cheap little script and suck down all the data into a database to use and repurpose as you see nessessary. When the API is in JavaScript it is a little more tedious. When you have a web service you don’t usually mind giving away all the content, unless you want to serve ads with your content, like google does (and who can really blame them).
This is going to become more and more common among companies who value sharing data, but survive on maintaining and displaingy that data. In five minutes of searching, I found 10+ examples of this technique (primarily in Google and Yahoo APIs). The ease of use, the general usefulness and pseudo protection of data all makes this technique a bit of a no-brainer. But how easy is it for them to implement? Extremely! Keep reading to see my solution to this problem.
I run a site called DCRails. It is a Google Maps mashup with the Washington DC Metrorail stops plotted out. One thing I frequently find myself needing is, which stop is the closest and the distance to that stop from a given location. I am happy to make this data freely available to the public, even though I don’t know how useful it will be any one else. Here is how it works.
Include this in your head tag
<script src="http://dcrails.com/api/closest_metro_js"
type="text/javascript" charset="utf-8"></script>
That is the API, to use it, it is a one liner.
new DCRails.MetroSearcher(lat,lng,callback);
Obviously, the lat is the latitude, the lng is the longitude and the callback is the function you want called when the MetroSearcher gathers the data.
That is all fine and dandy, but how does it work?
Well in my implementation it all comes down to tight coupling between the client-side and the server-side. Usually this is considered a no-no, but in this case you control both so if a better solution presents itself in the future you are free to change it. I will show you the entire API in two parts, and explain how it works.
if(!JsOnDemand) {
var JsOnDemand = {};
JsOnDemand.callbacks = {};
JsOnDemand.num = 0;
JsOnDemand.Get = function(url, callback) {
this.callback = callback;
var id = JsOnDemand.num++;
JsOnDemand.callbacks[id] = this;
var script = document.createElement('script');
script.type = 'text/javascript';
var t = new Date();
var cacheDefeater = '' + t.getYear() +
t.getMonth() +
t.getDay() +
t.getHours() +
t.getMinutes() +
t.getSeconds() +
id;
script.src = 'http://dcrails.com' +
url + "&JsOnDemandNum=" + id +
'&__no_cache=' + cacheDefeater;
document.getElementsByTagName('head')[0].appendChild(script);
}
}
That is the first object, it essentially makes a dynamic script tag of the url and stores the callback function.
if(!DCRails) var DCRails = {};
DCRails.MetroSearcher = function(lat, lng, callback) {
new JsOnDemand.Get("/map/closest_stop?lat=" +
lat + "&lng=" + lng, callback)
}
That is the definition of the DCRails.MetroSearcher object. It provides the user a nice callable function that takes in the exact parameters it requires and hopefully the user has. You can see it calls JsOnDemand.Get from the first part.
The trick to making this work is what the server-side returns. Remember that since we are requesting a script tag, whatever gets returned needs to be run-able JavaScript. It also needs to call the function we specified. My solution isn’t the most elegant, but it works flawlessly. Here is what the server returns.
eval(JsOnDemand.callbacks[0].callback(
{"closest_metro_stop":{
"name":"McPherson Square",
"id":16},
"closest_metro_exit":{
"latitude":38.9005,
"longitude":-77.0322,
"name":"Franklin Square, 14th st.",
"id":24},
"distance":0.189}));
delete JsOnDemand.callbacks[0];
It looks in the JsOnDemand.callbacks hash for the first (0) callback because this is the first request on this web page. It knows to do this because the JsOnDemand object adds a query string parameter called JsOnDemandNum. The server must look for the parameter and uses it to construct the js. You end up with the afore mentioned response. The last thing the response does is clean up the reference to the callback that was used.
I think this is a valuable technique to understand if you are a client-side developer. If you understand how it works, you can get a feel for the limitations of using this approach.
I have tested this on several browsers (IE 6, IE 7, Firefox 2, Safari 2, and Opera 9) with no problems or limitations.
As a quick aside to any RoR users out there. Watch out for my plugin that makes this all work magically. Expected release date sooner than Feb. 5 2007. I need to understand the new REST stuff in rails and try to integrate where I see fit.
Published February 23, 2007 Reads 7,445
Copyright © 2007 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Nicholas Schlueter
Nicholas Schlueter runs DCRails (www.dcrails.com) and blogs at www.simpltry.com about JavaScript, Prototype, and why you shouldn't fear the coming revolution.
- It's the Java vs. C++ Shootout Revisited!
- Patterns for Building High Performance Applications
- Asynchronous Logging Using Spring
- Java for Programmers (2nd Edition)
- Cross-Platform Mobile Website Development – a Tool Comparison
- Three Buzzwords That Every CIO Hears but One They Should Listen To
- Write Once Run Anywhere or Cross Platform Mobile Development Tools
- Immersing into JavaScript Frameworks
- Workday Reportedly Prepping to Go Public
- Cloud Expo New York: The Java EE 7 Platform - Developing for the Cloud
- Book Review: Sams Teach Yourself Java in 24 Hours
- OpenOffice.com Lives
- Book Excerpt: Introducing HTML5
- Adobe Sends Flex to the Apache Foundation
- Five Years Waiting for JRE 7: Is It Justified? (Part 1)
- Book Excerpt: Java Application Profiling Tips and Tricks
- i-Technology in 2012: Five Industry Predictions
- It's the Java vs. C++ Shootout Revisited!
- Patterns for Building High Performance Applications
- OpenXava 4.3: Rapid Java Web Development
- The Next Web Architecture
- Asynchronous Logging Using Spring
- Java for Programmers (2nd Edition)
- Is Write Once Run Anywhere Ever Going to Be a Reality?
- A Cup of AJAX? Nay, Just Regular Java Please
- Java Developer's Journal Exclusive: 2006 "JDJ Editors' Choice" Awards
- JavaServer Faces (JSF) vs Struts
- The i-Technology Right Stuff
- Rich Internet Applications with Adobe Flex 2 and Java
- Java vs C++ "Shootout" Revisited
- Bean-Managed Persistence Using a Proxy List
- Reporting Made Easy with JasperReports and Hibernate
- Creating a Pet Store Application with JavaServer Faces, Spring, and Hibernate
- Why Do 'Cool Kids' Choose Ruby or PHP to Build Websites Instead of Java?
- What's New in Eclipse?
- i-Technology Predictions for 2007: Where's It All Headed?


















