JSONP解决跨域请求问题

时间:2022-11-21 21:53:43

一、何为跨域请求?

由于浏览器同源策略,不允许跨域请求数据,凡是发送请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。具体可以查看下表:
JSONP解决跨域请求问题

二、JSONP的由来

1、一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准;

2、不过我们又发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如script,img等标签);

3、于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理;

  4、恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据;

  5、这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。

  6、客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但其实并不一样。

  7、为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

  如果对于callback参数如何使用还有些模糊的话,我们后面会有具体的实例来讲解。

三、JSONP的实现

可以使用jsonp解决跨域的问题,具体步骤:
1、在js中不能跨域请求数据,js可以跨域请求js片段。
2、可以把数据包装成js片段。可以把数据使用js方法来包装,形成一条方法的调用语句。
3、可以使用ajax请求js片段,当js判断到达浏览器会被立即执行。
4、在浏览器端,先创建好回调方法,在回调方法中通过参数可以获得请求的数据。
JSONP解决跨域请求问题

前提准备:
1、需要把js的回调方法先写好。(此处为getDataService方法)

getDataService: function(a) {
var b = [], c = this;
$.each(a.data, function(a) {
this.index = a, "l" == this.t && (this.i = c.FN_RefactorJSON(this.i, 7)), b.push(c.renderItem(this, a))
});
b.push('<div class="extra"><a {if pageConfig.isHome}clstag="homepage|keycount|home2013|0614a"{/if} href="http://www.jd.com/allSort.aspx">\u5168\u90e8\u5546\u54c1\u5206\u7c7b</a></div>'), this.OBJ.attr("load", "1").html(b.join("")), $.bigiframe(this.OBJ), this.FN_GetBrands();
var d = this, e = this.OBJ.outerWidth(), f = this.OBJ.outerHeight();
$("#_JD_ALLSORT").dropdown({delay: 0,onmouseleave: function() {
$("#_JD_ALLSORT .item").removeClass("hover")
}}, function(a) {
var b, c, g = document.documentElement.scrollTop + document.body.scrollTop, h = $("#nav-2013").offset().top + 39;
h >= g ? (c = a.hasClass("fore13") ? 3 : 3, g = c) : (b = a.offset().top, g = g > b - 5 ? b - h - 10 : Math.max(3, g - h));
var i = a.find(".i-mc");
if (i.css({top: g + "px"}), d.OBJ.find("iframe")) {
var j = i.outerWidth() + e, k = i.outerHeight() > f ? i.outerHeight() : f;
d.OBJ.find("iframe").css({width: j,height: k,top: g})
}
})
}

2、做ajax请求时,需要把回调方法的方法名传递给服务端。(传递一个callback参数)

URL_Serv: "http://localhost:8080/rest/category.json?callback=category.getDataService",//跨哉的情况下

3、服务端接收回调方法名,把数据包装好,响应给客户端。
将json数据包装成js。

category.getDataService({"data":[{"u":"products/1.html","n":"<a href='products/1.html'>图书、音像、电子书刊</a>","i":[{"u":"products/2.html","n":"电子书刊","i":["products/3.html|电子书","products/4.html|网络原创","products/5.html|数字杂志","products/6.html|多媒体图书"]}]});