26.1.06 # Remote Json

Jason I really like Json and use it as a data exchange format between client and server for quite some time.

Yahoo! and del.icio.us are prominent representatives that currently offer web services based upon Json.

In order to use these web services in your web page you unfortunately cannot use standard Ajax without a proxy script on your web server.

As a way out of this we can adopt the dynamic <script> element approach. In his well written article Jason Levitt illustrates, how to access Json data from remote web servers.

Despite the benefit of this solution using a <script> element – either static or dynamic, one problem remains depending on the way, the remote server is wrapping the Json data:

  1. {"a":"b"}
    There is no way to deal with anonymous data recieved by the <script> element.
  2. var x={"a":"b"}
    Here the data is accessible through variable x, which is visible in the client's global scope. However the exact time of the data availability is not known, as it is delivered by an asynchron process.
  3. f({"a":"b"});
    This is the best way, as the function f will get called automatically, when the data is available. But how do remote web service and web client agree upon the function name?
    1. The web service rigidly dictates the name of the callback function.
    2. The web client sends the callback name as part of its request.

I wrote a javascript function remoteJson that handles incoming Json data according to cases 2. + 3. from static as well as dynamic <script> elements.

That function remoteJson(listener) expects a single object as argument. The optional data members of this object are:

"uri":
The uri to get the Json data from, which is equivalent to the src-attribute of the dynamic <script> element. When omitted, a corresponding static <script> element is expected in the same document.
"callback":
A reference to the callback function with no arguments. When omitted, an automatic callback from the web service according to case 3. will occur.
"condition":
A boolean javascript expression as a string, which will be evaluated to decide, if the Json data has been completely loaded. Only needed in combination with callback.

An example call to del.icio.us with a static <script> element might be:

remoteJson({"callback": function(){alert(Delicious.posts.length);},
            "condition": "typeof(Delicious) != 'undefined'"});

with the corresponding <script> element somewhere on the same page. The alternative call creating a dynamic <script> element looks like so:

remoteJson({"uri": "http://del.icio.us/feeds/json/yourname/",
            "callback": function(){alert(Delicious.posts.length);},
            "condition": "typeof(Delicious) != 'undefined'"});

And making a call relying on the server calling back into a provided function might look like:

remoteJson({"uri": "http://del.icio.us/feeds/json/yourname?callback=f"});

Finally here is the implementation of remoteJson:

function remoteJson(listener) {
   if (listener && listener.uri) { // create dynamic script element. 
      script = document.getElementById("remotejson");
      if (script) // script element may exist from previous call, so ..
         script.parentNode.removeChild(script);  // .. delete it.
      script = document.createElement("script"); // new script element.
      script.setAttribute("type", "text/javascript");
      script.setAttribute("id", "remotejson");
      script.setAttribute("src", listener.uri);
      document.getElementsByTagName("head")[0].appendChild(script);
   }
   if (listener && listener.condition && listener.callback)
      var timer = setInterval(function(){
                                 if (eval(listener.condition)) {
                                     clearInterval(timer);
                                     listener.callback(listener.target);
                                 }
                              }, 500);
}

This function basically works by periodically testing the provided condition twice a second and when true, the callback function is invoked.

It's a pity, that current browsers don't support the onload event handler also for the <script> element as they do with the <body> and <img> elements. This would make the function presented here obsolete.

3 comments

Well done!
[url=http://xjznrxtr.com/ipti/biqc.html]My homepage[/url] | [url=http://qorcpkmx.com/aipb/vdiy.html]Cool site[/url]
 

Well done!
My homepage | Please visit
 

Thank you!
http://xjznrxtr.com/ipti/biqc.html | http://dzmuydqs.com/gqvl/eryx.html
 
Kommentar veröffentlichen