Jsonp -- JSON+Padding
JS对JSONP的实现
jsonp是json用来跨域的一个东西。原理是通过script标签的跨域特性来绕过同源策略。
script标签的src属性是可以直接实现跨域的,这是标签特性,所以我们可以借助它来实现跨域。
简单实现:
index.html
<button>ajax</button>
{% csrf_token %}
<script>
function func(name){ //func写在src请求的上面,不然找不到这个func函数,我们请求的另一个网站的后端,返回的数据就是这个函数名称加参数的形式 // # HttpResponse("func('xx')")
alert(name)
}
</script>
<script src="http://127.0.0.1:8000/SendAjax/"></script>
flask
from django.views.decorators.csrf import csrf_exempt
import json
@csrf_exempt #如果跨域请求是post请求,别忘了csrftoken可能会产生的阻拦,get请求不需要加上它
def SendAjax(request):
# dic={"k1":"v1"}
return HttpResponse("func('xx')") # return HttpResponse("func('%s')"%json.dumps(dic))
# 注意,func这个名称是另外那个发送请求的网站的一个js代码函数名称
JSONP的原型:创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。
将JSON数据填充进回调函数,这就是JSONP的JSON+Padding的含义。
进阶版:
<button onclick="f()">sendAjax</button>
<script>
function addScriptTag(src){
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
document.body.removeChild(script);
}
function func(name){ // 接受返回数据的回调函数
alert("hello"+name)
}
function f(){
addScriptTag("http://127.0.0.1:8002/SendAjax/?callbacks=func") // callbacks这个名称不是固定的,和另一个网站的服务端商量好就行了,就是后端取值时的一个参数而已
}
</script>
views
def SendAjax(request):
import json
dic={"k1":"v1"}
print("callbacks:",request.GET.get("callbacks"))
callbacks=request.GET.get("callbacks")
return HttpResponse("%s('%s')"%(callbacks,json.dumps(dic)))
jQuery对JSONP的实现
getJSON
jQuery框架也当然支持JSONP,可以使用$.getJSON(url,[data],[callback])方法。
html:
<button onclick="f()">sendAjax</button>
<script>
function f(){
$.getJSON("http://127.0.0.1:8000/SendAjax/?callbacks=?",function(arg){
alert("hello"+arg)
});
}
</script>
注意的是在url的后面必须添加一个callbacks(callbacks名不是固定的)参数,这样getJSON方法才会知道是用JSONP方式去访问服务,callbacks后面的那个问号是内部自动生成的一个回调函数名。
$.ajax
如果想指定自己的回调函数名,或者说服务上规定了固定回调函数名,可以使用$.ajax方法来实现。
<script>
function f(){
$.ajax({ //type请求方法没写,默认是get请求
url:"http://127.0.0.1:8000/SendAjax/",
dataType:"jsonp",
jsonp: 'callbacks',
jsonpCallback:"SayHi"
});
}
function SayHi(arg){
alert(arg.k1); //k1是后端返回的数据中的键值对的键
}
</script>
或者通过回调函数处理:较简单
<script>
function f(){
$.ajax({
url:"http://127.0.0.1:8002/SendAjax/",
dataType:"jsonp", //必须有,告诉server,这次访问要的是一个jsonp的结果。
jsonp: 'callbacks', //jQuery帮助随机生成的:callbacks="wner"
success:function(data){
alert("hi "+data)
}
});
}
</script>
jsonp: 'callbacks'就是定义一个存放回调函数的键,jsonpCallback是前端定义好的回调函数方法名'SayHi',server端接受callback键对应值后就可以在其中填充数据打包返回了;
jsonpCallback参数可以不定义,jquery会自动定义一个随机名发过去,那前端就得用回调函数来处理对应数据了。利用jQuery可以很方便的实现JSONP来进行跨域访问。
注意 JSONP一定是GET请求
应用:
<input type="button" onclick="AjaxRequest()" value="跨域Ajax"/>
<div id="container"></div>
<script type="text/javascript">
function AjaxRequest() {
$.ajax({
url: 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403',
type: 'GET',
dataType: 'jsonp',
jsonp: 'callback',
jsonpCallback: 'list',
success: function (data) {
$.each(data.data,function(i){
var item = data.data[i];
var str = "<p>"+ item.week +"</p>";
$('#container').append(str);
$.each(item.list,function(j){
var temp = "<a href='" + item.list[j].link +"'>" + item.list[j].name +" </a><br/>";
$('#container').append(temp);
});
$('#container').append("<hr/>");
})
}
});
}
</script>