JSONP:JSON With Padding
含义:可以理解为请求后端API,服务器会在传给浏览器前将JSON数据填充到回调函数(parseResponse)中
主要原理:
1.Script标签,通过src的方式去加载某一个服务器下的资源
2.用Script标签加载资源是没有跨域问题的,可以加载任何类型的文件
以上方式存在一个缺点:
- 当页面一加载就开始执行,不能异步请求,做到按需加载
- 需求:从某个服务器获取一段文本内容,获取之后在控制台打印,示意前端代码:
<!DOCTYPE html>
<html>
<head>
<title>js跨域问题-jsonp</title>
<!--JSONP方式 JSON with Padding:可以理解为内填充-->
<!--1.首先定义一个函数用来处理返回的函数-->
<script type="text/javascript">
function fn(data){
console.log(data);
}
</script>
<!--2.从服务端加载需要请求的数据,举例请求地址为:http://api.douban.com/book/subjects?q=javascript&alt=xd&callback=fn1 此地址可以修改q进行搜索豆瓣服务器端的图书资源-->
<script type="text/javascript" src="http://www.example.com/todo/api/v1.0/tasks?callback=fn"></script>
</head>
<body>
</body>
</html>
后端示意代码,以python的flask为例:
# coding=UTF-8
import json
from os import abort
from flask import request, Flask, jsonify
app = Flask(__name__)
tasks = [
{
'id': 1,
'title': u'Buy groceries',
'description': u'Milk, Cheese, Pizza, Fruit, Tylenol',
'done': False
},
{
'id': 2,
'title': u'Learn Python',
'description': u'Need to find a good Python tutorial on the web',
'done': False
}
]
@app.route('/todo/api/v1.0/tasks', methods=['POST',"GET"])
def create_task():
print request.args
# if not request.json or not 'title' in request.json:
# abort(400)
task = {
'id': tasks[-1]['id'] + 1,
'title': "test",
'description': "hah",
'done': False
}
tasks.append(task)
# 这里定义callback主要是为了动态返回客户端需要执行的全局函数名称
callback = request.args.get('callback')
jsonData = "{\"id\":\"3\", \"name\":\"zhangsan\", \"telephone\":\"13612345678\"}"
retStr = callback + "(" + json.dumps(task) + ")"
return retStr
if __name__ == '__main__':
app.debug = True
app.run()
通过以上方式,我们便通过JSONP的方式成功访问到了服务器跨域的资源。
JSONP优点
它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都 可以运行,
不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。
JSONP缺点
它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
Jsonp的执行过程如下:
首先在客户端注册一个callback (如:'jsoncallback'), 然后把callback的名字(如:jsonp1236827957501)传给服务器。注意:服务端得到callback的数值后,要用jsonp1236827957501(......)
把将要输出的json内容包括起来,
此时,服务器生成 json 数据才能被客户端正确接收。
然后以 javascript 语法的方式,生成一个function, function 名字就是传递上来的参数 'jsoncallback'的值 jsonp1236827957501 .
最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。
客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时javascript文档数据,作为参数, 传入到了客户端预先定义好的 callback 函数(如上例中jquery $.ajax()方法
封装的的success: function (json))里。
可以说jsonp的方式原理上和<script src="http://跨域/...xx.js"></script>是一致的(qq空间就是大量采用这种方式来实现跨域数据交换的)。
JSONP是一种脚本注入(Script Injection)行为,所以有一定的安全隐患。