XMLHttpRequests blocked
The issue is this: In the web browser, you use XMLHttpRequest to access data from a different server, in order to create some kind of "mashup" application. Browser security restricts this unless the remote server returns special headers indicating that this is allowed. This is shown in Figure 1, below, with a typical JSON request, such as when trying to access JSON data from Twitter: http://search.twitter.com/search.json?q=dartlang![]() |
| Figure 1. XMLHttpRequest response data is blocked by browser security |
JSONP workaround
This has already been solved in JavaScript by using a callback. The data returned is wrapped in a JavaScript function call (known as a callback), so that when the data is received, the browser calls the callback function, passing in the returned data. This is known as JSONP, with the url now having a new callback parameter (specifying the callback function name), for example: http://search.twitter.com/search.json?q=dartlang&callback=onDataReceivedUsing JSONP with Dart
Unfortunately, this is trying to call a JavaScript function, and not a Dart function. At present, the only way to communicate between JavaScript and Dart in the same application is by using window.postMessage in JavaScript and adding a handler with window.on.message.add( ... ) in Dart. Seth Ladd discusses how to achieve this for JSONP callbacks in his blog post, and the flow is much like that shown in Figure 2.![]() |
| Figure 2 - Using JSONP with a JavaScript callback and window.postmessage |
Introducing the DartJSONP library
This all works fine, but you need to write some boilerplate code, such as manually adding a JavaScript callback function to your html, and writing a postMessage handler to receive the data. If you want to receive data from multiple, separate sites, you also need to design a way to tell the difference between the different callbacks sent by postMessage.In order to make this simpler, I have created the DartJSONP library, which automates the task that Seth describes in Option 2 on his blog post. This allows you to call out to multiple servers and get JSONP data back with minimal code.
The following example shows how you can access some Twitter data using DartJSONP which defines the class JsonpCallback. You create an instance of the object, passing in the name of the callback (which can be any valid function name). Then when you call the doCallback(url) function, the DartJSONP library takes care of all the JavaScript and postMessage handling, simply returning the data in the onDataReceived handler.
var callbackFuncName = "twitterFunction";
JsonpCallback twitterCallback = new JsonpCallback(callbackFuncName);
twitterCallback.onDataReceived = (Map data) {
// do something with the returned data
};
var twitterUrl = "http://search.twitter.com/search.json?q=dartlang&callback=$callbackFuncName";
twitterCallback.doCallback(twitterUrl);
Internally, JSONP will dynamically add the JavaScript callback function, invoke the call to the remote server, post the response back to JavaScript, which posts the data back to Dart.
You can see this running by navigating to this link: http://example.dartwatch.com/jsonp/DartJsonPtest.html which loads data from Google Plus and Twitter (it's the example that is used in the test currently on github).
JSONP is available on Github.
References:
Seth's blog post where the JSONP and postMessage handling is described
MDN documentation on CORS - which is how web servers can avoid the requirement for clients to use JSONP



