一看就懂:jsonp详解


Posted in Javascript onJune 01, 2015

json相信大家都用的多,jsonp我就一直没有机会用到,但也经常看到,只知道是“用来跨域的”,一直不知道具体是个什么东西。今天总算搞明白了。下面一步步来搞清楚jsonp是个什么玩意。

同源策略

首先基于安全的原因,浏览器是存在同源策略这个机制的,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性。看起来不知道什么意思,实践一下就知道了。

1、随便建两个网页

一个端口是2698,一个2701,按照定义它们是不同源的。

一看就懂:jsonp详解

2.用jQuery发起不同源的请求
在2698端口的网页上添加一个按钮,Click事件随便发起两个向端口为2701域的请求。

$("#getOtherDomainThings").click(function () {

    $.get("http://localhost:2701/Scripts/jquery-1.4.4.min.js", function (data) {

        console.log(data)

    })
    $.get("http://localhost:2701/home/index", function (data) {

        console.log(data)

    })

})

根据同源策略,很明显会悲剧了。浏览器会阻止,根本不会发起这个请求。(not allowed by Access-Control-Allow-Origin)

一看就懂:jsonp详解

OK,原来jsonp是要解决这个问题的。

script标签的跨域能力
不知道大家知不知道CDN这个东西,例如微软的CDN,使用它,我们的网页可以不提供jQuery,由微软的网站帮我们提供:

<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js" type="text/javascript"></script>

回到我们的2698端口的网页,上面我们在Click事件里有一个对2701端口域的jQuery文件的请求,这次使用script标签来请求。
<script type="text/javascript" src="http://localhost:2701/Scripts/jquery-1.4.4.min.js"></script>

当然,200,OK了

一看就懂:jsonp详解

同样是端口2698的网页发起对2701域的请求,放在script里设置scr属性的OK了,另一个方式就悲剧。利用script的跨域能力,这就是jsonp的基础。

利用script获取不同源的json
既然它叫jsonp,很明显目的还是json,而且是跨域获取。根据上面的分析,很容易想到:利用js构造一个script标签,把json的url赋给script的scr属性,把这个script插入到dom里,让浏览器去获取。实践:

function CreateScript(src) {

    $("<script><//script>").attr("src", src).appendTo("body")

}

添加一个按钮事件来测试一下:
$("#getOtherDomainJson").click(function () {

    $.get('http://localhost:2701/home/somejson', function (data) {

        console.log(data)

    })

})

一看就懂:jsonp详解

首先,第一个浏览器,http://localhost:2701/home/somejson这个Url的确是存在一个json的,而且在 2698网页上用script标签来请求这个2701这个Url也是200OK的,但是最下面报js语法错误了。原来用script标签加载完后,会立即 把响应当js去执行,很明显{"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"}不是合法的js语句。

利用script获取异域的jsonp

显然,把上面的json放到一个回调方法里是最简单的方法。例如,变成这样:

一看就懂:jsonp详解

如果存在jsonpcallback这个方法,那么jsonpcallback({"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"})就是合法的js语句。

由于服务器不知道客户端的回调是什么,不可能hard code成jsonpcallback,所以就带一个QueryString让客户端告诉服务端,回调方法是什么,当然,QueryString的key要遵从服务端的约定,上面的是”callback“。

添加回调函数:

function jsonpcallback(json) {

    console.log(json)

}

把前面的方法稍微改改参数:
$("#getJsonpByHand").click(function () {

    CreateScript("http://localhost:2701/home/somejsonp?callback=jsonpcallback")

})

一看就懂:jsonp详解

200OK,服务器返回jsonpcallback({"Email":"zhww@outlook.com","Remark":"我来自遥远的 东方"}),我们也写了jsonpcallback方法,当然会执行。OK顺利获得了json。没错,到这里就是jsonp的全部。

利用jQuery获取jsonp
上面的方式中,又要插入script标签,又要定义一个回调,略显麻烦,利用jQuery可以直接得到想要的json数据,同样是上面的jsonp:

$("#getJsonpByJquery").click(function () {

    $.ajax({

        url: 'http://localhost:2701/home/somejsonp',

        dataType: "jsonp",

        jsonp: "callback",

        success: function (data) {

            console.log(data)

        }

    })

})

得到的结果跟上面类似。

总结

一句话就是利用script标签绕过同源策略,获得一个类似这样的数据,jsonpcallback是页面存在的回调方法,参数就是想得到的json。

jsonpcallback({"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"})

ADD 原生js:

<button id="btn">click</button>

<script type="text/javascript">

    function $(str){

        return document.getElementById(str)

    }

    function CreateScript(src) {

        var Scrip=document.createElement('script');

        Scrip.src=src;

        document.body.appendChild(Scrip);

    }

    function jsonpcallback(json) {

            console.log(json);//Object { email="中国", email2="中国222"}

    }

    $('btn').onclick=function(){

      CreateScript("http://localhost:51335/somejson?callback=jsonpcallback")    

    }

</script>
Javascript 相关文章推荐
javascript 面向对象继承
Nov 26 Javascript
如何正确使用javascript 来进行我们的程序开发
Jun 23 Javascript
jQuery中ajax的get()方法用法实例
Dec 26 Javascript
javascript 解决浏览器不支持的问题
Sep 24 Javascript
javaScript+turn.js实现图书翻页效果实例代码
Feb 16 Javascript
jQuery操作之效果详解
May 19 jQuery
jQuery 循环遍历改变a标签的href(实例讲解)
Jul 12 jQuery
Vue.js 点击按钮显示/隐藏内容的实例代码
Feb 08 Javascript
el-select 下拉框多选实现全选的实现
Aug 02 Javascript
vue.js实现二级菜单效果
Oct 19 Javascript
简单了解JavaScript sort方法
Nov 25 Javascript
vue v-on:click传递动态参数的步骤
Sep 11 Javascript
JS数组array元素的添加和删除方法代码实例
Jun 01 #Javascript
JQuery判断checkbox是否选中及其它复选框操作方法合集
Jun 01 #Javascript
window.onload与$(document).ready()的区别分析
May 30 #Javascript
JQuery给网页更换皮肤的方法
May 30 #Javascript
jQuery实现给页面换肤的方法
May 30 #Javascript
js获取滚动距离的方法
May 30 #Javascript
jquery简单实现外部链接用新窗口打开的方法
May 30 #Javascript
You might like
Apache 配置详解(最好的APACHE配置教程)
2010/07/04 PHP
PHP与MySQL开发的8个技巧小结
2010/12/17 PHP
linux下编译安装memcached服务
2014/08/03 PHP
php基于openssl的rsa加密解密示例
2016/07/11 PHP
Yii2框架RESTful API 格式化响应,授权认证和速率限制三部分详解
2016/11/10 PHP
利用PHP获取访客IP、地区位置、浏览器及来源页面等信息
2017/06/27 PHP
laravel框架实现敏感词汇过滤功能示例
2020/02/15 PHP
JavaScript 捕获窗口关闭事件
2009/07/26 Javascript
登陆成功后自动计算秒数执行跳转
2014/01/23 Javascript
js中document.write的那点事
2014/12/12 Javascript
HTML5canvas 绘制一个圆环形的进度表示实例
2016/12/16 Javascript
前端框架学习总结之Angular、React与Vue的比较详解
2017/03/14 Javascript
JavaScript实现审核流程状态的动态显示进度条
2017/03/15 Javascript
node.js express中app.param的用法详解
2017/07/16 Javascript
js图片放大镜实例讲解(必看篇)
2017/07/17 Javascript
Vue.js 中取得后台原生HTML字符串 原样显示问题的解决方法
2018/06/10 Javascript
vue组件定义,全局、局部组件,配合模板及动态组件功能示例
2019/03/19 Javascript
js核心基础之构造函数constructor用法实例分析
2019/05/11 Javascript
vue 实现超长文本截取,悬浮框提示
2020/07/29 Javascript
javascript 数组(list)添加/删除的实现
2020/12/17 Javascript
详解python脚本自动生成需要文件实例代码
2017/02/04 Python
基于numpy.random.randn()与rand()的区别详解
2018/04/17 Python
django 删除数据库表后重新同步的方法
2018/05/27 Python
python读取xlsx的方法
2018/12/25 Python
Python 微信之获取好友昵称并制作wordcloud的实例
2019/02/21 Python
flask 实现上传图片并缩放作为头像的例子
2020/01/09 Python
详解HTML5中的拖放事件(Drag 和 drop)
2016/11/14 HTML / CSS
Unix控制后台进程都有哪些进程
2016/09/22 面试题
护理学应聘自荐书范文
2014/02/05 职场文书
酒店秘书求职信范文
2014/02/17 职场文书
环保倡议书400字
2014/05/15 职场文书
优秀学生党员先进事迹材料
2014/05/29 职场文书
派出所副所长四风问题个人整改措施思想汇报
2014/10/13 职场文书
唐山大地震的观后感
2015/06/05 职场文书
CSS实现章节添加自增序号的方法
2021/06/23 HTML / CSS
教你使用Ubuntu搭建DNS服务器
2022/09/23 Servers