出身背景
您应该尽可能使用CORS(即您的服务器或API支持它,浏览器支持足够),因为JSONP具有固有的安全风险。
示例
JSONP(带填充的JSON)是一种常用于绕过web浏览器中的跨域策略。(您不允许对浏览器认为位于不同服务器上的网页发出AJAX请求。)
JSON和JSONP在客户端和服务器上的行为不同。JSONP请求不会使用XMLHTTPRequest和关联的浏览器方法进行调度。而是创建一个<script>标记,其源设置为目标URL。然后将此脚本标记添加到DOM(通常在<head>元素内)。
JSON请求:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
// success
};
};
xhr.open("GET", "somewhere.php", true);
xhr.send();
JSONP请求:
var tag = document.createElement("script");
tag.src = 'somewhere_else.php?callback=foo';
document.getElementsByTagName("head")[0].appendChild(tag);
JSON响应和JSONP响应之间的区别在于,JSONP应答对象作为参数传递给回调函数。
JSON:
{ "bar": "baz" }
日本电话:
foo( { "bar": "baz" } );
这就是为什么您看到包含回调参数的JSONP请求,以便服务器知道包装响应的函数的名称。
当浏览器评估<script>标记时(请求完成后),该函数必须存在于全局范围中。
处理JSON响应和JSONP响应之间需要注意的另一个区别是,JSON响应中的任何解析错误都可以通过包装对responseText求值的尝试来捕获在try/catch语句中。由于JSONP响应的性质,响应中的解析错误将导致无法缓存的JavaScript解析错误。
这两种格式都可以通过在启动请求之前设置超时并在响应处理程序中清除超时来实现超时错误。
使用jQuery
使用jQuery发出JSONP请求的有用之处在于,jQuery在后台为您完成所有工作。
默认情况下,jQuery要求您包含&callback=?在AJAX请求的URL中。jQuery将接受您指定的成功函数,为其分配一个唯一的名称,并将其发布到全局范围中。然后它将取代问号?在回调中=?使用它指定的名称。
比较类似的JSON和JSONP实现
以下假定响应对象{“bar”:“baz”}
JSON:
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);