我可以在不使用jQuery或其他外部库的情况下在JavaScript中创建跨域JSONP请求吗?我想使用JavaScript本身,然后解析数据并使其成为一个对象,以便我可以使用它。我必须使用外部库吗?如果没有,我该怎么办?
答案 0 :(得分:148)
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
答案 1 :(得分:35)
轻量级示例(支持onSuccess和onTimeout)。如果需要,您需要在URL中传递回调名称。
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
答案 2 :(得分:26)
什么是JSONP?
使用jsonp要记住的重要一点是它实际上不是协议或数据类型。它只是一种即时加载脚本并处理引入页面的脚本的方法。本着JSONP的精神,这意味着将新的javascript对象从服务器引入客户端应用程序/脚本。
JSONP何时需要?
这是一种允许一个域同时访问/处理同一页面中另一个域的数据的方法。主要是,它用于覆盖在XHR(ajax)请求中发生的CORS(跨源资源共享)限制。脚本加载不受CORS限制。
如何完成
从服务器引入新的javascript对象可以通过多种方式实现,但最常见的做法是让服务器实现“回调”函数的执行,并将所需的对象传递给它。回调函数只是您已在客户端上设置的函数,脚本在脚本加载点处加载调用以处理传入其中的数据。
示例:强>
我有一个应用程序可以将所有项目记录在某人的家中。我的应用程序已设置好,我现在想要检索主卧室中的所有项目。
我的申请是app.home.com
。我需要加载来自api.home.com
的数据。
除非明确设置服务器以允许它,否则我无法使用ajax加载此数据,因为即使是单独子域上的页面也会受到XHR CORS限制。
理想情况下,设置为允许x-domain XHR
理想情况下,由于api和app位于同一个域中,因此我可能有权在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解决方案无法实现。在我的客户端脚本上设置JSONP:我设置了一个函数,用于在进行 JSONP调用时处理来自服务器的响应。:
function processJSONPResponse(data) {
var dataFromServer = data;
}
需要设置服务器以返回类似"processJSONPResponse({"room":"main bedroom","items":["bed","chest of drawers"]});"
之类的迷你脚本。如果调用//api.home.com?getdata=room&room=main_bedroom
之类的内容,它可能会返回这样的字符串。
然后客户端设置脚本标记:
var script = document.createElement('script');
script.src = '//api.home.com?getdata=room&room=main_bedroom';
document.querySelector('head').appendChild(script);
这会加载脚本并立即调用window.processJSONPResponse()
作为写入/ echo /打印出来的服务器。作为函数的参数传入的数据现在存储在dataFromServer
局部变量中,无论您需要什么,都可以使用它。
清理
一旦客户有数据,即。将脚本添加到DOM后,可以立即从DOM中删除脚本元素:
script.parentNode.removeChild(script);
答案 3 :(得分:17)
我的理解是你实际上使用了带有JSONP的脚本标签,sooo ......
第一步是创建将处理JSON的函数:
function hooray(json) {
// dealin wit teh jsonz
}
确保可以在全局级别访问此功能。
接下来,向DOM添加一个脚本元素:
var script = document.createElement('script');
script.src = 'http://domain.com/?function=hooray';
document.body.appendChild(script);
该脚本将加载API提供程序构建的JavaScript并执行它。
答案 4 :(得分:8)
我使用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);
});
参考:
JavaScript XMLHttpRequest using JsonP
http://www.w3ctech.com/topic/721(谈谈使用Promise的方式)
答案 5 :(得分:6)
我有一个纯粹的javascript库来执行https://github.com/robertodecurnex/J50Npi/blob/master/J50Npi.js
请查看它并告诉我您是否需要使用或理解代码。
顺便说一句,您在这里有一个简单的用法示例:http://robertodecurnex.github.com/J50Npi/
答案 6 :(得分:5)
/**
* 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');
答案 7 :(得分:2)
我尽可能简单地编写了一个库来处理这个问题。无需外部,只需一个功能。与其他一些选项不同,此脚本自行清理,并在运行时进行进一步请求。
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);
};
});
}
答案 8 :(得分:1)
请在下面的 JavaScript
示例中查看,以便在没有JQuery的情况下进行 JSONP
调用:
此外,您可以参考我的 GitHub
存储库以供参考。
https://github.com/shedagemayur/JavaScriptCode/tree/master/jsonp
window.onload = function(){
var callbackMethod = 'callback_' + new Date().getTime();
var script = document.createElement('script');
script.src = 'https://jsonplaceholder.typicode.com/users/1?callback='+callbackMethod;
document.body.appendChild(script);
window[callbackMethod] = function(data){
delete window[callbackMethod];
document.body.removeChild(script);
console.log(data);
}
}
答案 9 :(得分:0)
/**
* 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' );
答案 10 :(得分:0)
如果您使用ES6和NPM,您可以尝试节点模块“fetch-jsonp”。 Fetch API支持将JsonP调用作为常规XHR调用。
先决条件:
您应该在堆栈中使用pair<int,int> findLongestConseqSubseq(int arr[], int n)
{
pair<int,int> max; //starting index, length
max.second = 1;
max.first=0;
pair<int,int> current;
current.second = 1;
current.first=0;
int i;
for (i = 1; i < n; i++) {
if (arr[i] == arr[i-1])
{ /* the run continues */
current.second++;
if (current.second > max.second)
{
max.second = current.second;
max.first = current.first;
}
}
else
{
current.second=1;
current.first=i;
}
}
return max;
}
节点模块。
答案 11 :(得分:0)
只需粘贴ES6版本的sobstel的好答案:
send(someUrl + 'error?d=' + encodeURI(JSON.stringify(json)) + '&callback=c', 'c', 5)
.then((json) => console.log(json))
.catch((err) => console.log(err))
function send(url, callback, timeout) {
return new Promise((resolve, reject) => {
let script = document.createElement('script')
let timeout_trigger = window.setTimeout(() => {
window[callback] = () => {}
script.parentNode.removeChild(script)
reject('No response')
}, timeout * 1000)
window[callback] = (data) => {
window.clearTimeout(timeout_trigger)
script.parentNode.removeChild(script)
resolve(data)
}
script.type = 'text/javascript'
script.async = true
script.src = url
document.getElementsByTagName('head')[0].appendChild(script)
})
}