jsonp本质上是利用<script>
不受同源策略限制的特性,创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。
将JSON数据填充进回调函数,这就是JSONP的JSON+Padding的含义。
案例
views.py
1 | def abc(request): |
js
1 | $.ajax({ |
打开页面后
因为同源策略限制跨域发送ajax请求。
细心点的同学应该会发现我们的views.py
其实已经接收到了请求并返回了响应,是浏览器对非同源请求返回的结果做了拦截。
我们使用cdn方式引用的jQuery文件也是跨域的,它就可以使用。
同样是从其他的站点拿东西,script标签就可以。那我们能不能利用这一点搞点事情呢?
修改html
文件
1 | <button id="b1">点我</button> |
我们刷新一下页面
看来后端返回的响应已经被拿到了,只不过把rion
当成了一个变量来使用,但是该页面上却没有定义一个名为rion
的变量。所以出错了。
定义一个rion
变量
1 | <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> |
这次就不会报错了。
那可不可以定义一个函数呢?
1 | <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> |
同时把返回的响应也改一下:
1 | def abc(request): |
我返回的 rion()
,页面上拿到这个响应之后直接执行了rion
函数!
那函数中可不可以传递参数呢?
1 | <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> |
1 | def abc(request): |
我们通过script标签的跨域特性来绕过同源策略拿到想要的数据了!!!
这其实就是JSONP的简单实现模式,或者说是JSONP的原型:创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。
将JSON数据填充进回调函数,这就是JSONP的JSON+Padding的含义。
但是我们更多时候是希望通过事件触发数据的获取,而不是像上面一样页面一刷新就执行了,这样很不灵活。
其实这很好解决,我们可以通过javascript
动态的创建script
标签来实现。
1 | <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> |
这样当我们点击b1按钮的时候,会在页面上插入一个script标签,然后从后端获取数据。
为了实现更加灵活的调用,我们可以把客户端定义的回调函数的函数名传给服务端,服务端则会返回以该回调函数名,将获取的json
数据传入这个函数完成回调。