此问题已经在这里有了答案:
我知道JSONP
是带填充的JSON
。
我了解JSON是什么,以及如何在jQuery.getJSON()
中使用它。但是,在引入JSONP时,我不理解jQuery.getJSON()
的概念。
谁能向我解释这是如何工作的?
此答案已超过6年历史。虽然JSONP的概念和应用没有改变(即答案的详细信息仍然有效),您应该callback
(即您的look to use CORS where possible或server支持它,并且API就足够了),作为JSONP browser support。
JSONP(带有填充的JSON)是一种通常用于绕过Web浏览器中的跨域策略。 (不允许您向浏览器认为在其他服务器上的网页发出AJAX请求。)
JSON和JSONP在客户端和服务器上的行为不同。不会使用has inherent security risks和关联的浏览器方法调度JSONP请求。而是创建一个XMLHTTPRequest
标签,其源设置为目标URL。然后将此脚本标签添加到DOM(通常在<script>
元素内部)。
<head>
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
// success
};
};
xhr.open("GET", "somewhere.php", true);
xhr.send();
[JSON响应和JSONP响应之间的区别在于JSONP响应对象作为参数传递给回调函数。
var tag = document.createElement("script");
tag.src = 'somewhere_else.php?callback=foo';
document.getElementsByTagName("head")[0].appendChild(tag);
{ "bar": "baz" }
这就是为什么您看到包含foo( { "bar": "baz" } );
参数的JSONP请求,以便服务器知道用于包装响应的函数的名称。
此函数必须存在在全局范围内当时 callback
标记由浏览器评估(一旦请求完成)。
要注意的是,在处理JSON响应和JSONP响应之间的另一个区别是,可以通过包装尝试评估responseText的方法来捕获JSON响应中的任何解析错误。在try / catch语句中。由于JSONP响应的性质,响应中的解析错误将导致不可捕获的JavaScript解析错误。
两种格式都可以通过在发起请求之前设置超时并在响应处理程序中清除超时来实现超时错误。
使用<script>
发出JSONP请求的有用之处在于,jQuery在后台为您做了所有工作。
默认情况下,jQuery要求您在AJAX请求的URL中包含jQuery。 jQuery将采用您指定的&callback=?
函数,为其分配一个唯一的名称,并将其发布到全局范围内。然后它将用其分配的名称替换success
中的问号?
。
以下假定响应对象&callback=?
{ "bar" : "baz" }
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
document.getElementById("output").innerHTML = eval('(' + this.responseText + ')').bar;
};
};
xhr.open("GET", "somewhere.php", true);
xhr.send();
说您有一些可以给您提供JSON数据的URL,例如:
function foo(response) {
document.getElementById("output").innerHTML = response.bar;
};
var tag = document.createElement("script");
tag.src = 'somewhere_else.php?callback=foo';
document.getElementsByTagName("head")[0].appendChild(tag);
...,您有一个类似的URL,除了它使用JSONP外,还向其传递了回调函数名称“ myCallback”(通常通过给它一个名为“ callback”的查询参数来完成,例如{'field': 'value'}
)。然后它将返回:
http://example.com/dataSource?callback=myCallback
...这不仅是一个对象,而且实际上是可以执行的代码。因此,如果您在页面的其他位置定义一个名为myCallback({'field':'value'})
的函数并执行此脚本,则会使用URL中的数据来调用该脚本。
关于这一点的奇妙之处在于:您可以创建一个脚本标记并将URL(带有myFunction
参数完成)用作callback
属性,然后浏览器将运行它。这意味着您可以绕过“同源”安全策略(因为浏览器允许您从页面域以外的来源运行脚本标签)。
这是当您发出ajax请求时(使用src
和'jsonp'作为.ajax
属性的值时,jQuery所做的事情)。例如:
.ajax
[这里,jQuery处理回调函数名称和查询参数-使API与其他ajax调用相同。但是,与前面提到的其他类型的Ajax请求不同,您不受限于从与页面相同来源获取数据。
JSONP是绕过浏览器dataType
的一种方法。怎么样?像这样:
$.ajax({
url: 'http://example.com/datasource',
dataType: 'jsonp',
success: function(data) {
// your code to handle data here
}
});
这里的目标是在响应中请求same-origin policy和名称。通常我们会提出AJAX请求:
otherdomain.com
但是,由于请求将发送到另一个域,因此无法正常工作。
尽管我们可以使用alert
标签进行请求。 $.get('otherdomain.com', function (response) {
var name = response.name;
alert(name);
});
和<script>
都将导致发出相同的请求:
<script src="otherdomain.com"></script>
Q:但是,如果我们使用$.get('otherdomain.com')
标签,那么我们如何访问响应?如果要GET otherdomain.com
,需要访问它。
A:嗯,我们不能。但是,这就是我们可以做的-定义一个使用响应的函数,然后告诉服务器使用JavaScript响应,该JavaScript以响应作为参数调用我们的函数。
问:但是如果服务器不为我们做这件事,只愿意将JSON返回给我们怎么办?
A:那么我们将无法使用它。 JSONP需要服务器进行协作。
Q:必须使用<script>
标签很丑。
A:类似jQuery alert
的库。例如:
<script>
它通过动态创建make it nicer标签DOM元素来工作。
Q:$.ajax({
url: "http://otherdomain.com",
jsonp: "callback",
dataType: "jsonp",
success: function( response ) {
console.log( response );
}
});
标签仅发出GET请求-如果我们要发出POST请求怎么办?
A:那么JSONP将不适用于我们。
问:可以,我只想发出GET请求。 JSONP很棒,我将继续使用它-谢谢!
A:实际上,那不是那么棒。它实际上只是一个hack。并使用<script>
。现在CORS可用了,您应该尽可能使用它。
我找到了一篇有用的文章,该文章也非常清楚易懂地解释了该主题。链接为<script>
一些值得注意的要点是:
工作如下: