如何在没有 JQuery 的情况下从 Javascript 发出 JSONP 请求?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6132796/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to make a JSONP request from Javascript without JQuery?
提问by Dave
Can I make a cross-domain JSONP request in JavaScript without using jQuery or other external library? I would like to use JavaScript itself and then parse the data and make it an object so I could use it. Do I have to use an external library? If not, how can I do it?
我可以在不使用 jQuery 或其他外部库的情况下在 JavaScript 中发出跨域 JSONP 请求吗?我想使用 JavaScript 本身,然后解析数据并将其设为对象,以便我可以使用它。我必须使用外部库吗?如果没有,我该怎么做?
回答by Matt Ball
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
回答by sobstel
Lightweight example (with support for onSuccess and onTimeout). You need to pass callback name within URL if you need it.
轻量级示例(支持 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;
})();
Sample usage:
示例用法:
$jsonp.send('some_url?callback=handleStuff', {
callbackName: 'handleStuff',
onSuccess: function(json){
console.log('success!', json);
},
onTimeout: function(){
console.log('timeout!');
},
timeout: 5
});
At GitHub: https://github.com/sobstel/jsonp.js/blob/master/jsonp.js
在 GitHub:https: //github.com/sobstel/jsonp.js/blob/master/jsonp.js
回答by dewd
What is JSONP?
什么是 JSONP?
The important thing to remember with jsonp is that it isn't actually a protocol or data type. Its just a way of loading a scripton the fly and processing the script that is introduced to the page. In the spirit of JSONP, this means introducing a new javascript object from the server into the client application/ script.
使用 jsonp 需要记住的重要一点是它实际上不是协议或数据类型。它只是一种动态加载脚本并处理引入页面的脚本的方法。本着 JSONP 的精神,这意味着将一个新的 javascript 对象从服务器引入到客户端应用程序/脚本中。
When is JSONP needed?
什么时候需要 JSONP?
It is 1 method of allowing one domain to access/ process data from another in the same page asyncronously. Primarily, it is used to override CORS (Cross Origin Resource Sharing) restrictions which would occur with an XHR (ajax) request. Script loads are not subject to CORS restrictions.
这是一种允许一个域异步访问/处理同一页面中另一个域的数据的方法。主要用于覆盖 XHR (ajax) 请求会发生的 CORS(跨源资源共享)限制。脚本加载不受 CORS 限制。
How is it done
怎么做的
Introducing a new javascript object from the server can be implemented in many ways, but the most common practice is for the server to implement the execution of a 'callback' function, with the required object passed into it. The callback function is just a function you have already set up on the client which the scriptyou load calls at the point the scriptloads to process the data passed in to it.
从服务器引入一个新的 javascript 对象可以通过多种方式实现,但最常见的做法是让服务器实现“回调”函数的执行,并将所需的对象传递给它。回调函数只是您已经在客户端上设置的一个函数,您加载的脚本会在脚本加载时调用该函数来处理传递给它的数据。
Example:
例子:
I have an application which logs all items in someone's home. My application is set up and I now want to retrieve all the items in the main bedroom.
我有一个应用程序可以记录某人家中的所有项目。我的应用程序已设置,现在我想检索主卧室中的所有物品。
My application is on app.home.com
. The apis I need to load data from are on api.home.com
.
我的应用程序在app.home.com
. 我需要从中加载数据的 api 位于api.home.com
.
Unless the server is explicitly set up to allow it, I cannot use ajax to load this data, as even pages on separate subdomains are subject to XHR CORS restrictions.
除非服务器明确设置为允许它,否则我无法使用 ajax 加载此数据,因为即使是单独子域上的页面也受 XHR CORS 限制。
Ideally, set things up to allow x-domain XHR
理想情况下,设置允许 x 域 XHR
Ideally, since the api and app are on the same domain, I might have access to set up the headers on api.home.com
. If I do, I can add an Access-Control-Allow-Origin:
header item granting access to app.home.com
. Assuming the header is set up as follows: Access-Control-Allow-Origin: "http://app.home.com"
, this is far more secure than setting up JSONP. This is because app.home.com
can get everything it wants from api.home.com
without api.home.com
giving CORS access to the whole internet.
理想情况下,由于 api 和应用程序在同一个域中,我可能有权在api.home.com
. 如果我这样做,我可以添加一个Access-Control-Allow-Origin:
标题项,授予对app.home.com
. 假设 header 设置如下:Access-Control-Allow-Origin: "http://app.home.com"
,这比设置 JSONP 安全得多。这是因为无需让 CORS 访问整个互联网app.home.com
即可获得所需的一切。api.home.com
api.home.com
The above XHR solution isn't possible. Set up JSONP On my client script:I set up a function to process the reponse from the server when I make the JSONP call.:
上述 XHR 解决方案是不可能的。设置 JSONP 在我的客户端脚本上:我设置了一个函数来在我进行JSONP 调用时处理来自服务器的响应。:
function processJSONPResponse(data) {
var dataFromServer = data;
}
The server will need to be set up to return a mini script looking something like "processJSONPResponse({"room":"main bedroom","items":["bed","chest of drawers"]});"
It might be designed to return such a string if something like //api.home.com?getdata=room&room=main_bedroom
is called.
服务器将需要设置为返回一个看起来像"processJSONPResponse({"room":"main bedroom","items":["bed","chest of drawers"]});"
这样的迷你脚本如果//api.home.com?getdata=room&room=main_bedroom
调用类似的东西,它可能被设计为返回这样的字符串。
Then the client sets up a script tag as such:
然后客户端设置一个脚本标签,如下所示:
var script = document.createElement('script');
script.src = '//api.home.com?getdata=room&room=main_bedroom';
document.querySelector('head').appendChild(script);
This loads the script and immediately calls window.processJSONPResponse()
as written/ echo/ printed out by the server. The data passed in as the parameter to the function is now stored in the dataFromServer
local variable and you can do with it whatever you need.
这会加载脚本并立即调用window.processJSONPResponse()
服务器所写/回显/打印出来的内容。作为参数传入函数的数据现在存储在dataFromServer
局部变量中,您可以随心所欲地使用它。
Clean up
清理
Once the client has the data, ie. immediately after the script is added to the DOM, the script element can be removed from the DOM:
一旦客户端拥有数据,即。将脚本添加到 DOM 后,可以立即从 DOM 中删除脚本元素:
script.parentNode.removeChild(script);
回答by sdleihssirhc
My understanding is that you actually use script tags with JSONP, sooo...
我的理解是,您实际上将脚本标记与 JSONP 一起使用,所以...
The first step is to create your function that will handle the JSON:
第一步是创建将处理 JSON 的函数:
function hooray(json) {
// dealin wit teh jsonz
}
Make sure that this function is accessible on a global level.
确保可以在全局级别访问此功能。
Next, add a script element to the DOM:
接下来,向 DOM 添加一个脚本元素:
var script = document.createElement('script');
script.src = 'http://domain.com/?function=hooray';
document.body.appendChild(script);
The script will load the JavaScript that the API provider builds, and execute it.
该脚本将加载 API 提供者构建的 JavaScript,并执行它。
回答by derek
the way I use jsonp like below:
我使用 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)
});
}
then use 'jsonp' method like this:
然后像这样使用'jsonp'方法:
jsonp('http://xxx/cors').then(function(data){
console.log(data);
});
reference:
参考:
JavaScript XMLHttpRequest using JsonP
使用 JsonP 的 JavaScript XMLHttpRequest
http://www.w3ctech.com/topic/721(talk about the way of use Promise)
http://www.w3ctech.com/topic/721(说说Promise的使用方式)
回答by robertodecurnex
I have a pure javascript library to do that https://github.com/robertodecurnex/J50Npi/blob/master/J50Npi.js
我有一个纯 javascript 库来做到这一点https://github.com/robertodecurnex/J50Npi/blob/master/J50Npi.js
Take a look at it and let me know if you need any help using or understanding the code.
看看它,如果您在使用或理解代码方面需要任何帮助,请告诉我。
Btw, you have simple usage example here: http://robertodecurnex.github.com/J50Npi/
顺便说一句,这里有简单的使用示例:http: //robertodecurnex.github.com/J50Npi/
回答by Konstantin Tarkus
/**
* 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);
});
})();
Usage sample:
使用示例:
const data = await load('http://api.github.com/orgs/kriasoft');
回答by Fresheyeball
I wrote a library to handle this, as simply as possible. No need to make it external, its just one function. Unlike some other options, this script cleans up after itself, and is generalized for making further requests at runtime.
我写了一个库来尽可能简单地处理这个问题。无需将其外部化,它只是一个功能。与其他一些选项不同,此脚本会在其自身之后进行清理,并被通用化以在运行时发出进一步的请求。
https://github.com/Fresheyeball/micro-jsonp
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);
};
});
}
回答by Mayur S
Please find below JavaScript
example to make a JSONP
call without JQuery:
请找到以下JavaScript
示例以在JSONP
没有 JQuery 的情况下进行调用:
Also, you can refer my GitHub
repository for reference.
另外,您可以参考我的GitHub
存储库以供参考。
https://github.com/shedagemayur/JavaScriptCode/tree/master/jsonp
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);
}
}
回答by just_user
Just pasting an ES6 version of sobstel's nice answer:
只是粘贴一个 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)
})
}