85 lines
1.6 KiB
JavaScript
85 lines
1.6 KiB
JavaScript
|
|
||
|
/**
|
||
|
* Module dependencies
|
||
|
*/
|
||
|
|
||
|
var debug = require('debug')('jsonp');
|
||
|
|
||
|
/**
|
||
|
* Module exports.
|
||
|
*/
|
||
|
|
||
|
module.exports = jsonp;
|
||
|
|
||
|
/**
|
||
|
* Callback index.
|
||
|
*/
|
||
|
|
||
|
var count = 0;
|
||
|
|
||
|
/**
|
||
|
* Noop function.
|
||
|
*/
|
||
|
|
||
|
function noop(){};
|
||
|
|
||
|
/**
|
||
|
* JSONP handler
|
||
|
*
|
||
|
* Options:
|
||
|
* - param {String} qs parameter (`callback`)
|
||
|
* - timeout {Number} how long after a timeout error is emitted (`60000`)
|
||
|
*
|
||
|
* @param {String} url
|
||
|
* @param {Object|Function} optional options / callback
|
||
|
* @param {Function} optional callback
|
||
|
*/
|
||
|
|
||
|
function jsonp(url, opts, fn){
|
||
|
if ('function' == typeof opts) {
|
||
|
fn = opts;
|
||
|
opts = {};
|
||
|
}
|
||
|
|
||
|
var opts = opts || {};
|
||
|
var param = opts.param || 'callback';
|
||
|
var timeout = null != opts.timeout ? opts.timeout : 60000;
|
||
|
var enc = encodeURIComponent;
|
||
|
var target = document.getElementsByTagName('script')[0];
|
||
|
var script;
|
||
|
var timer;
|
||
|
|
||
|
// generate a unique id for this request
|
||
|
var id = count++;
|
||
|
|
||
|
if (timeout) {
|
||
|
timer = setTimeout(function(){
|
||
|
cleanup();
|
||
|
fn && fn(new Error('Timeout'));
|
||
|
}, timeout);
|
||
|
}
|
||
|
|
||
|
function cleanup(){
|
||
|
target.parentNode.removeChild(script);
|
||
|
window['__jp' + id] = noop;
|
||
|
}
|
||
|
|
||
|
window['__jp' + id] = function(data){
|
||
|
debug('jsonp got', data);
|
||
|
if (timer) clearTimeout(timer);
|
||
|
cleanup();
|
||
|
fn && fn(null, data);
|
||
|
};
|
||
|
|
||
|
// add qs component
|
||
|
url += (~url.indexOf('?') ? '&' : '?') + param + '=' + enc('__jp' + id + '');
|
||
|
url = url.replace('?&', '?');
|
||
|
|
||
|
debug('jsonp req "%s"', url);
|
||
|
|
||
|
// create script
|
||
|
script = document.createElement('script');
|
||
|
script.src = url;
|
||
|
target.parentNode.insertBefore(script, target);
|
||
|
};
|