Skip to content

Instantly share code, notes, and snippets.

@Integralist
Created November 16, 2011 17:25
Show Gist options
  • Save Integralist/1370735 to your computer and use it in GitHub Desktop.
Save Integralist/1370735 to your computer and use it in GitHub Desktop.
JSONP Async Loading via RequireJs
require.config({
paths: {
jsonp: 'Plugins/jsonp'
}
});
require(['jsonp!http://twitter.com/statuses/user_timeline/Integralist.json?callback=rjs_global',
'jsonp!http://twitter.com/statuses/user_timeline/Barracat.json?callback=rjs_global',
'jsonp!http://api.twitter.com/1/trends/available.json?callback=rjs_global'], function(feed1, feed2, feed3) {
console.log('feed1: ', feed1);
console.log('feed2: ', feed2);
console.log('feed3: ', feed3);
});
require(['jsonp!JSON-P.php?callback=rjs_global'], function(feed4) {
console.log('feed4: ', feed4);
});
<?php
header('Content-Type: text/javascript; charset=utf8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Max-Age: 3628800');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
// Callback function
$callback = $_GET['callback'];
// JSON data
$data = '{"name":"mark mcdonnell"}';
// Delay sending the data back (this is to mimic latency)
sleep(5);
echo $callback.'('.$data.');';
?>
define(function(){
function loadScript(url, callback) {
var d = document,
b = d.body,
callback = (typeof callback !== "undefined") ? callback : function(){},
script = d.createElement("script");
script.type = "text/javascript";
if (script.readyState) { // Internet Explorer
script.onreadystatechange = function() {
if (script.readyState == "loaded" || script.readyState == "complete") {
/*
* Oddly the final readyState isn’t always "complete".
* Sometimes, readyState stops at "loaded" without going on to "complete"
* and sometimes it skips over "loaded" altogether.
*
* The best approach is to check for both readyState values
* and remove the event handler in both cases to ensure you don’t handle the loading twice:
*/
script.onreadystatechange = null;
callback(true);
}
};
} else {
script.onload = function() {
callback(true);
};
}
script.src = url;
b.insertBefore(script, b.firstChild); // can be a problem if the BODY doesn't exist
}
// Create global variable for jsonp service to execute
window['rjs_global'] = function(data) {
// Create global variable to store returned data
window['rjs_jsonp'] = data;
};
return {
/**
* @param resource { String } the resource to be loaded
* @param req { Function } a local require() for loading other modules
* @param load { Function } a function to call with the value for name (this tells the loader that the plugin is done loading the resource)
* @param config { Object } the main configuration object RequireJs is using
*/
load: function(resource, req, load, config) {
loadScript(resource, function(loaded){
if (loaded && ('rjs_jsonp' in window)) {
load(window['rjs_jsonp']);
}
});
}
};
});
@unscriptable
Copy link

This looks great, @Integralist. I hope you don't mind if I brag, but jsonp just works in curl.js! :D

curl(
    ['http://twitter.com/statuses/user_timeline/Integralist.json?callback=define', 
    'http://twitter.com/statuses/user_timeline/Barracat.json?callback=define'], 
    function(feed1, feed2) {
        console.log(feed1);
        console.log(feed2);
    }
);

@jrburke
Copy link

jrburke commented Nov 16, 2011

See also Miller's async plugin which should handle jsonp calls too. It uses a unique ID for each jsonp callback which may be safer when multiple calls are involved?

@Integralist
Copy link
Author

@unscriptable thanks for the heads up, I'll be checking that out! :-)
@jrburke thanks, I've had a quick look at his plugin and can see that he generates a unique id so I'll see if I can work something like that into this

Cheers for the input!

@Integralist
Copy link
Author

@jrburke I've had to file a bug for the async plugin because it was causing issues (millermedeiros/requirejs-plugins#1) I've also updated my code (see above) to include a call to a local JSON-P script (again see above) which uses sleep() to simulate latency and it all seems to work fine as it is.

So I might not bother with unique id's for the time being (I'll also see what comes of that bug I filed as that might change my perspective) /cc @millermedeiros

Screenshots...

Network: http://cl.ly/17341L3r130D1j2K0u3e
Console: http://cl.ly/2I3A3g173r3u2W1v1u47

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment