1.JSONP原理剖析以及实现
1.1 同源策略限制
用django分别建立两个项目,jsonp01和jsonp02,然后再在这两个项目里分别建立一个app,比如名字叫jsonp1、jsonp2;jsonp01的端口号是8005,jsonp02的端口号是8006。
jsonp1的代码如下,
setting做常规配置;
urls.py,
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^testjsonp/', views.testjsonp), url(r'^index/', views.index), ]
views.py,
def testjsonp(request): return HttpResponse('OK') def index(request): return render(request,'index.html')
index.html,
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" onclick="ajaxjsonp1();" value="jsonp1" /> <script src="/static/js/jquery-1.12.4.js"></script> <script> function ajaxjsonp1() { $.ajax({ url : '/testjsonp/', type : 'POST', data: {'k1':'v1'}, success : function (data) { alert(data); } }); } </script> </body> </html>
jsonp2的代码如下,
settings.py做常规配置;
urls.py,
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^testjsonp2/', views.testjsonp2), ]
views.py,
def testjsonp2(request): return HttpResponse('jsonp2ok')
如上面的代码,因为jsonp1请求的是自己的项目域名(url : '/testjsonp/'),所以会如期收到返回的数据并alert(ok);
当把url : '/testjsonp/'改成url : 'http://10.103.9.83:8006/testjsonp2/',即用ajax实现跨域请求(好比在www.taobao.com上通过ajax访问www.jd.com的数据),则会报错如下图,
这是因为自身浏览器的同源策略限制,比如在www.taobao.com上通过ajax访问www.jd.com的数据,该请求能从自己的浏览器发送到jd.com服务端,服务端也能处理并返回数据,但是当自己的浏览器发现收到的数据是非本机域名发来的,就会阻拦该数据,过程如下图,
,通过ajax,如果在当前域名去访问其他域名时,浏览器会出现同源策略限制,从而阻止请求的返回,所以无法用ajax实现跨域请求。
1.2 解决同源策略
img、script、iframe、link这些标签是不受同源策略限制的;src属性一般不鸟同源策略。利用这个特点,就可以实现jsonp的跨域请求。
改进jsonp1的index.html的代码,
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" onclick="ajaxjsonp1();" value="jsonp1" /> <input type="button" onclick="ajaxjsonp2();" value="jsonp2" /> <script src="/static/js/jquery-1.12.4.js"></script> <script> function ajaxjsonp1() { $.ajax({ url : 'http://10.103.9.83:8005 /testjsonp/', type : 'POST', data: {'k1':'v1'}, success : function (data) { alert(data); } }); } function ajaxjsonp2() { #创建一个script标签,src值设置为要请求的域名,将这个标签加到head标签下,请求完之后remove掉这个标签。 var tag = document.createElement("script"); tag.src = "http://10.103.9.83:8006/testjsonp2/"; document.head.appendChild(tag); document.head.removeChild(tag); } </script> </body> </html>
然后点击index.html的“jsonp2”按钮,就会收到如下报错:
,这说明本地浏览器已经收到服务端返回的数据(jsonp2ok)了,但是这个返回的数据是交给javascripts处理的,因为script里没有“jsonp2ok”这个方法,所以会报错“jsonp2ok没有定义”,所以需要在服务端和客户端再做一些修改,代码见下,
jsonp2的views.py,
import json def testjsonp2(request): ll = ['jack','luce','goi'] #直接返回一个jsonpfunc(ll),然后客户端的script标签里需要定义一个jsonpfunc方法,然后就能处理数据了。 temp = 'jsonpfunc(%s)' % (json.dumps(ll)) return HttpResponse(temp)
jsonp1的index.html,
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" onclick="ajaxjsonp1();" value="jsonp1" /> <input type="button" onclick="ajaxjsonp2();" value="jsonp2" /> <script src="/static/js/jquery-1.12.4.js"></script> <script> function ajaxjsonp1() { $.ajax({ url : 'http://10.103.9.83:8005 /testjsonp/', type : 'POST', data: {'k1':'v1'}, success : function (data) { alert(data); } }); } function ajaxjsonp2() { var tag = document.createElement("script"); tag.src = "http://10.103.9.83:8006/testjsonp2/"; document.head.appendChild(tag); document.head.removeChild(tag); } #收到服务端返回的数据,然后执行下面的jsonpfunc方法。 function jsonpfunc(data) { console.log(data); } </script> </body> </html>
现在再点击jsonp1的index.html的"jsonp2"按钮,返回数据见下:
,客户端收到这些数据后,就可以处理了。
1.3 利用jquery实现伪ajax的跨域请求
上面讲的是jsonp的原理,原理就是利用那些不受同源策略限制的标签来发送请求,下面要说的是利用jquery实现伪ajax的跨域请求。
function weiajax(){ $.ajax({ url : 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403', type : 'GET', dataType : 'jsonp', jsonp : 'callback', jsonpCallback : 'list' }); } function list(arg){ console.log(arg); } #这样就能获取到江西卫视的节目单了。 #注意,上面的function list(arg){}和 jsonpCallback : 'list',之所以叫list,是因为江西卫视的服务器返回的数据中包含的javascript方法名叫list。
如果用是请求本地域名,就直接用ajax即可;如果是请求跨域数据,则依然用ajax,但是需要dataType : 'jsonp'、jsonp : 'callback'、jsonpCallback : 'funcdemo',然后再定义一个function funcdemo(arg){}方法。
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。