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