Created
June 18, 2009 18:18
-
-
Save gf3/132080 to your computer and use it in GitHub Desktop.
Simple JSONP in vanilla JS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* loadJSONP( url, hollaback [, context] ) -> Null | |
* - url (String): URL to data resource. | |
* - hollaback (Function): Function to call when data is successfully loaded, | |
* it receives one argument: the data. | |
* - context (Object): Context to invoke the hollaback function in. | |
* | |
* Load external data through a JSONP interface. | |
* | |
* ### Examples | |
* | |
* loadJSONP( | |
* 'http://www.gigpark.com/businesses/runlevel6.json', | |
* function(data) { | |
* console.log(data) | |
* } | |
* ) | |
**/ | |
var loadJSONP = (function loadJSONP_outer( window, document, undefined ) { var uuid, head, main_script | |
uuid = 0 | |
head = document.head || document.getElementsByTagName( 'head' )[0] | |
main_script = document.createElement( 'script' ) | |
main_script.type = 'text/javascript' | |
return function loadJSONP_inner( url, callback, context ) { var name, script | |
// INIT | |
name = '__jsonp_' + uuid++ | |
if ( url.match(/\?/) ) | |
url += '&callback=' + name | |
else | |
url += '?callback=' + name | |
// Create script | |
script = main_script.cloneNode() | |
script.src = url | |
// Setup handler | |
window[name] = function( data ) { | |
callback.call( ( context || window ), data ) | |
head.removeChild( script ) | |
script = null | |
delete window[name] | |
} | |
// Load JSON | |
head.appendChild( script ) | |
} | |
})( window, document ) | |
@DrStrangeLove It wouldn't be difficult to add a third argument, such as an options object. It could be used to control the name of the callback parameter.
I modified it a bit to act little bit more like the new fetch api and using promises
const fetchJSONP = (unique => url =>
new Promise(rs => {
// INIT
let script = document.createElement('script')
let name = "_jsonp_" + unique++
if (url.match(/\?/)) url += "&callback="+name
else url += "?callback="+name
script.src = url
window[name] = json => {
rs(new Response(JSON.stringify(json)))
script.remove()
delete window[name]
}
document.body.appendChild(script)
})
)(0)
More es2015 friendly and ESLinted according to AirBnb:
const fetchJSONP = (unique => url =>
new Promise(rs => {
const script = document.createElement('script');
const name = `_jsonp_${unique++}`;
if (url.match(/\?/)) {
url += `&callback=${name}`;
} else {
url += `?callback=${name}`;
}
script.src = url;
window[name] = json => {
rs(new Response(JSON.stringify(json)));
script.remove();
delete window[name];
};
document.body.appendChild(script);
})
)(0);
👍
can someone explain how it's works? because i have no idea.
Thanks for the code, it's good, but I wouldn't recommend using simple incrementation of counter to achieve unique callback name. I suggest using timestamp or random number. Although this code cleans up afterwards, when I used it twice in 2 widgets on the same site, there were collisions.
I used this solution:
https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Great gist!!
But what if some server script accepts different parameter instead of callback??
it could be http://xxx.yyy/script?jsonp=callbackname