一看就懂: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 相关文章推荐
分享十五个最佳jQuery 幻灯插件和教程
Mar 27 Javascript
用JavaScript计算在UTF-8下存储字符串占用字节数
Aug 08 Javascript
jQuery实现的动态伸缩导航菜单实例
May 07 Javascript
Angular.js中用ng-repeat-start实现自定义显示
Oct 18 Javascript
浅析JavaScript动画模拟拖拽原理
Dec 09 Javascript
微信小程序 自定义对话框实例详解
Jan 20 Javascript
js+css实现红包雨效果
Jul 12 Javascript
解决Angular4项目部署到服务器上刷新404的问题
Aug 31 Javascript
Vue Router 实现动态路由和常见问题及解决方法
Mar 06 Javascript
JS实现网页烟花动画效果
Mar 10 Javascript
jquery实现简单自动轮播图效果
Jul 29 jQuery
Nuxt.js nuxt-link与router-link的区别说明
Nov 06 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
自编函数解决pathinfo()函数处理中文问题
2014/11/03 PHP
php中文繁体和简体相互转换的方法
2015/03/21 PHP
Zend Framework教程之Zend_Form组件实现表单提交并显示错误提示的方法
2016/03/21 PHP
php提交表单时保留多个空格及换行的文本样式的方法
2017/06/20 PHP
jQuery 注意事项 与原因分析
2009/04/24 Javascript
javascript 获取url参数和script标签中获取url参数函数代码
2010/01/22 Javascript
基于jquery1.4.2的仿flash超炫焦点图播放效果
2010/04/20 Javascript
JS如何判断移动端访问设备并解析对应CSS
2013/11/27 Javascript
分享一则JavaScript滚动条插件源码
2015/03/03 Javascript
Javascript发送AJAX请求实例代码
2016/08/21 Javascript
js前端解决跨域问题的8种方案(最新最全)
2016/11/18 Javascript
vue axios 在页面切换时中断请求方法 ajax
2018/03/05 Javascript
echarts鼠标覆盖高亮显示节点及关系名称详解
2018/03/17 Javascript
JQuery获取元素尺寸、位置及页面滚动事件应用示例
2019/05/14 jQuery
vue select 获取value和lable操作
2020/08/28 Javascript
彻底搞懂并解决vue-cli4中图片显示的问题实现
2020/08/31 Javascript
[01:01:25]DOTA2上海特级锦标赛B组资格赛#2 Fnatic VS Spirit第三局
2016/02/27 DOTA
[01:09]模型精美,特效酷炫!TI9不朽宝藏Ⅰ鉴赏
2019/05/10 DOTA
Python实现拼接多张图片的方法
2014/12/01 Python
python批量提取word内信息
2015/08/09 Python
详解使用 pyenv 管理多个版本 python 环境
2017/10/19 Python
Flask解决跨域的问题示例代码
2018/02/12 Python
利用Anaconda简单安装scrapy框架的方法
2018/06/13 Python
Python如何调用JS文件中的函数
2019/08/16 Python
Python模拟伯努利试验和二项分布代码实例
2020/05/27 Python
Python绘制组合图的示例
2020/09/18 Python
基于python+selenium自动健康打卡的实现代码
2021/01/13 Python
Html5百叶窗效果的示例代码
2017/12/11 HTML / CSS
台湾屈臣氏网路商店:Watsons台湾
2020/12/29 全球购物
简历的自我评价
2014/02/03 职场文书
丑小鸭教学反思
2014/02/03 职场文书
校园绿化美化方案
2014/06/08 职场文书
民族学专业求职信
2014/07/28 职场文书
2014年个人工作总结范文
2014/11/07 职场文书
python实现简易自习室座位预约系统
2021/06/30 Python
详解Go语言中配置文件使用与日志配置
2022/06/01 Golang