一看就懂: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 相关文章推荐
js 动态为textbox添加下拉框数据源的方法
Apr 24 Javascript
JavaScript中的条件判断语句使用详解
Jun 03 Javascript
js关于getImageData跨域问题的解决方法
Oct 14 Javascript
JavaScript实现Fly Bird小游戏
Dec 15 Javascript
第一次记录Bootstrap table学习笔记(1)
May 18 Javascript
MUI实现上拉加载和下拉刷新效果
Jun 30 Javascript
Vue.js devtool插件安装后无法使用的解决办法
Nov 27 Javascript
webpack打包js的方法
Mar 12 Javascript
修改node.js默认的npm安装目录实例
May 15 Javascript
jQuery实现点击旋转,再点击恢复初始状态动画效果示例
Dec 11 jQuery
Vue 防止短时间内连续点击后多次触发请求的操作
Nov 11 Javascript
如何用vue实现网页截图你知道吗
Nov 17 Vue.js
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
在php和MySql中计算时间差的方法详解
2015/03/27 PHP
PHP PDOStatement::errorInfo讲解
2019/01/31 PHP
关于JavaScript的gzip静态压缩方法
2007/01/05 Javascript
有趣的javascript数组定义方法
2010/09/10 Javascript
jQuery获取Select选择的Text和Value(详细汇总)
2013/01/25 Javascript
关于jQuery中的each方法(jQuery到底干了什么)
2014/03/05 Javascript
AngularJS中的过滤器使用详解
2015/06/16 Javascript
AngularJS中的Directive实现延迟加载
2016/01/25 Javascript
那些精彩的JavaScript代码片段
2017/01/12 Javascript
Canvas实现放射线动画效果
2017/02/15 Javascript
JS实现向iframe中表单传值的方法
2017/03/24 Javascript
JS轮播图实现简单代码
2021/02/19 Javascript
js replace 全局替换的操作方法
2018/06/12 Javascript
微信小程序云开发修改云数据库中的数据方法
2019/05/18 Javascript
基于JavaScript实现留言板功能
2020/03/16 Javascript
使用jQuery实现购物车
2020/10/29 jQuery
Python break语句详解
2014/03/11 Python
Python使用lxml模块和Requests模块抓取HTML页面的教程
2016/05/16 Python
Python文件操作基本流程代码实例
2017/12/11 Python
python爬虫爬取淘宝商品信息
2018/02/23 Python
python 实现判断ip连通性的方法总结
2018/04/22 Python
对Python3中bytes和HexStr之间的转换详解
2018/12/04 Python
python实现最大优先队列
2019/08/29 Python
MoviePy常用剪辑类及Python视频剪辑自动化
2020/12/18 Python
基于CSS3实现的黑色个性导航菜单效果
2015/09/14 HTML / CSS
澳大利亚旅游网站:Lastminute
2017/08/07 全球购物
澳大利亚宠物食品和用品商店:PETstock
2020/01/02 全球购物
应聘编辑自荐信范文
2014/03/12 职场文书
寒假家长评语大全
2014/04/16 职场文书
英语专业求职信
2014/07/08 职场文书
科技工作者先进事迹
2014/08/16 职场文书
上级领导检查欢迎词
2015/09/30 职场文书
信息技术远程培训心得体会
2016/01/09 职场文书
500字作文之难忘的同学
2019/12/20 职场文书
基于CSS3画一个iPhone
2021/04/21 HTML / CSS
阿里云k8s服务升级时502错误 springboot项目应用
2022/04/09 Servers