如何从没有JQuery的Javascript发出JSONP请求?

我可以在不使用jQuery或其他外部库的情况下在JavaScript中创build跨域JSONP请求吗? 我想使用JavaScript本身,然后parsing数据,并使其成为一个对象,所以我可以使用它。 我必须使用外部库吗? 如果没有,我该怎么办?

function foo(data) { // do stuff with JSON } var script = document.createElement('script'); script.src = '//example.com/path/to/jsonp?callback=foo' document.getElementsByTagName('head')[0].appendChild(script); // or document.head.appendChild(script) in modern browsers 

轻量级示例(支持onSuccess和onTimeout)。 如果需要,您需要在URL中传递callback名称。

 var $jsonp = (function(){ var that = {}; that.send = function(src, options) { var callback_name = options.callbackName || 'callback', on_success = options.onSuccess || function(){}, on_timeout = options.onTimeout || function(){}, timeout = options.timeout || 10; // sec var timeout_trigger = window.setTimeout(function(){ window[callback_name] = function(){}; on_timeout(); }, timeout * 1000); window[callback_name] = function(data){ window.clearTimeout(timeout_trigger); on_success(data); } var script = document.createElement('script'); script.type = 'text/javascript'; script.async = true; script.src = src; document.getElementsByTagName('head')[0].appendChild(script); } return that; })(); 

示例用法:

 $jsonp.send('some_url?callback=handleStuff', { callbackName: 'handleStuff', onSuccess: function(json){ console.log('success!', json); }, onTimeout: function(){ console.log('timeout!'); }, timeout: 5 }); 

在GitHub上: https : //github.com/sobstel/jsonp.js/blob/master/jsonp.js

什么是JSONP?

用jsonp记住的重要的事情是,它实际上不是一个协议或数据types。 它只是一种即时加载脚本并处理引入页面的脚本的方式。 本着JSONP的精神,这意味着从服务器引入一个新的JavaScript对象到客户端应用程序/脚本中。

什么时候需要JSONP?

允许一个域以asynchronous方式访问/处理同一页中的另一个域的数据是一种方法。 主要用于覆盖XHR(ajax)请求会发生的CORS(跨源资源共享)限制。 脚本加载不受CORS限制。

它是如何完成的

从服务器中引入一个新的JavaScript对象可以用很多方式实现,但最常见的做法是服务器执行一个“callback”函数,并将所需的对象传递给它。 callback函数只是您已经在客户端上设置的一个函数,您在加载脚本时会调用您加载的脚本来处理传递给它的数据。

例:

我有一个应用程序,logging在家里的所有项目。 我的应用程序已经build立,我现在想要检索主卧室中的所有物品。

我的应用程序在app.home.com 。 我需要加载数据的api.home.com是在api.home.com

除非服务器被明确设置为允许,否则我不能使用ajax来加载这些数据,因为即使是单独的子域中的页面也受到XHR CORS限制。

理想情况下,设置允许x域XHR

理想情况下,由于API和应用程序在同一个域上,我可能有权在api.home.com上设置标题。 如果我这样做,我可以添加Access-Control-Allow-Origin:标题项授予访问app.home.com 。 假设标头设置如下: Access-Control-Allow-Origin: "http://app.home.com" ,这比设置JSONP更安全。 这是因为app.home.com可以从api.home.com获得所需的一切,而不需要api.home.com给CORS访问整个互联网。

上述的XHR解决scheme是不可能的。 设置JSONP在我的客户端脚本中:当我进行JSONP调用时,我设置了一个函数来处理来自服务器的响应

 function processJSONPResponse(data) { var dataFromServer = data; } 

服务器将需要设置为返回一个类似于"processJSONPResponse({"room":"main bedroom","items":["bed","chest of drawers"]});"的小脚本"processJSONPResponse({"room":"main bedroom","items":["bed","chest of drawers"]});" 如果//api.home.com?getdata=room&room=main_bedroom被调用,它可能被devise为返回这样的string。

然后客户端设置一个脚本标签,如下所示:

 var script = document.createElement('script'); script.src = '//api.home.com?getdata=room&room=main_bedroom'; document.querySelector('head').appendChild(script); 

这加载脚本,并立即调用window.processJSONPResponse()作为书面/回声/打印出来的服务器。 作为parameter passing给函数的数据现在存储在dataFromServer局部variables中,您可以随时使用它。

清理

一旦客户端有数据,即。 脚本添加到DOM后,脚本元素可以从DOM中删除:

 script.parentNode.removeChild(script); 

我的理解是,你实际上使用脚本标记与JSONP,sooo …

第一步是创build将处理JSON的函数:

 function hooray(json) { // dealin wit teh jsonz } 

确保在全球范围内访问此function。

接下来,添加一个脚本元素到DOM:

 var script = document.createElement('script'); script.src = 'http://domain.com/?function=hooray'; document.body.appendChild(script); 

该脚本将加载API提供者构build的JavaScript,并执行它。

我有一个纯JavaScript库来做到这一点https://github.com/robertodecurnex/J50Npi/blob/master/J50Npi.js

看看它,让我知道如果你需要任何帮助使用或理解的代码。

顺便说一句,你有这里简单的使用示例: http : //robertodecurnex.github.com/J50Npi/

我使用jsonp的方式如下:

 function jsonp(uri){ return new Promise(function(resolve, reject){ var id = '_' + Math.round(10000 * Math.random()) var callbackName = 'jsonp_callback_' + id window[callbackName] = function(data){ delete window[callbackName] var ele = document.getElementById(id) ele.parentNode.removeChild(ele) resolve(data) } var src = uri + '&callback=' + callbackName var script = document.createElement('script') script.src = src script.id = id script.addEventListener('error', reject) (document.getElementsByTagName('head')[0] || document.body || document.documentElement).appendChild(script) }) } 

然后像这样使用'jsonp'方法:

 jsonp('http://xxx/cors').then(function(data){ console.log(data) }) 

参考:

使用JsonP的JavaScript XMLHttpRequest

http://www.w3ctech.com/topic/721 (说说使用Promise的方法)

 /** * Loads data asynchronously via JSONP. */ const load = (() => { let index = 0; const timeout = 5000; return url => new Promise((resolve, reject) => { const callback = '__callback' + index++; const timeoutID = window.setTimeout(() => { reject(new Error('Request timeout.')); }, timeout); window[callback] = response => { window.clearTimeout(timeoutID); resolve(response.data); }; const script = document.createElement('script'); script.type = 'text/javascript'; script.async = true; script.src = url + (url.indexOf('?') === -1 ? '?' : '&') + 'callback=' + callback; document.getElementsByTagName('head')[0].appendChild(script); }); })(); 

用法示例:

 const data = await load('http://api.github.com/orgs/kriasoft'); 

我尽可能简单地写了一个库来处理这个问题。 没有必要使它成为外部的,它只是一个function。 与其他一些选项不同的是,这个脚本自行清理,并在运行时进行进一步的请求。

https://github.com/Fresheyeball/micro-jsonp

 function jsonp(url, key, callback) { var appendParam = function(url, key, param){ return url + (url.indexOf("?") > 0 ? "&" : "?") + key + "=" + param; }, createScript = function(url, callback){ var doc = document, head = doc.head, script = doc.createElement("script"); script .setAttribute("src", url); head .appendChild(script); callback(function(){ setTimeout(function(){ head .removeChild(script); }, 0); }); }, q = "q" + Math.round(Math.random() * Date.now()); createScript( appendParam(url, key, q), function(remove){ window[q] = function(json){ window[q] = undefined; remove(); callback(json); }; }); } 
 /** * Get JSONP data for cross-domain AJAX requests * @private * @link http://cameronspear.com/blog/exactly-what-is-jsonp/ * @param {String} url The URL of the JSON request * @param {String} callback The name of the callback to run on load */ var loadJSONP = function ( url, callback ) { // Create script with url and callback (if specified) var ref = window.document.getElementsByTagName( 'script' )[ 0 ]; var script = window.document.createElement( 'script' ); script.src = url + (url.indexOf( '?' ) + 1 ? '&' : '?') + 'callback=' + callback; // Insert script tag into the DOM (append to <head>) ref.parentNode.insertBefore( script, ref ); // After the script is loaded (and executed), remove it script.onload = function () { this.remove(); }; }; /** * Example */ // Function to run on success var logAPI = function ( data ) { console.log( data ); } // Run request loadJSONP( 'http://api.petfinder.com/shelter.getPets?format=json&key=12345&shelter=AA11', 'logAPI' );