一看就懂: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中面向对象技术的模拟
Sep 25 Javascript
js调用webservice中的方法实现思路及代码
Feb 25 Javascript
js截取中英文字符串、标点符号无乱码示例解读
Apr 17 Javascript
删除Javascript Object中间的key
Nov 18 Javascript
jQuery插件制作之参数用法实例分析
Jun 01 Javascript
require.js的用法详解
Oct 20 Javascript
js获取及判断键盘按键的方法
Dec 01 Javascript
微信小程序 摇一摇抽奖简单实例实现代码
Jan 09 Javascript
jQuery滚动条美化插件nicescroll简单用法示例
Apr 18 jQuery
AngularJS中ng-options实现下拉列表的数据绑定方法
Aug 13 Javascript
JavaScript学习笔记之基于定时器实现图片无缝滚动功能详解
Jan 09 Javascript
解决mui框架中switch开关通过js控制开或者关状态时小圆点不动的问题
Sep 03 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
雄兵连:第三季确定会出,不过时间未定,鹤熙是第三季的主角!
2020/03/13 国漫
用Php实现链结人气统计
2006/10/09 PHP
php数组函数序列之each() - 获取数组当前内部指针所指向元素的键名和键值,并将指针移到下一位
2011/10/31 PHP
PHP得到某段时间区间的时间戳 php定时任务
2012/04/12 PHP
PHP 获取远程文件大小的3种解决方法
2013/07/11 PHP
PHP调用MySQL存储过程并返回值的方法
2014/12/26 PHP
在php和MySql中计算时间差的方法详解
2015/03/27 PHP
PHP面向对象之领域模型+数据映射器实例(分析)
2017/06/21 PHP
Thinkphp 框架扩展之应用模式实现方法分析
2020/04/27 PHP
JavaScript 通过模式匹配实现重载
2010/08/12 Javascript
基于jquery的设置页面文本框 只能输入数字的实现代码
2011/04/19 Javascript
JavaScript单元测试ABC
2012/04/12 Javascript
jquery post方式传递多个参数值后台以数组的方式进行接收
2013/01/11 Javascript
杨氏矩阵查找的JS代码
2013/03/21 Javascript
js数组的操作指南
2014/12/28 Javascript
JavaScript搜索字符串并将搜索结果返回到字符串的方法
2015/04/06 Javascript
JavaScript动态修改背景颜色的方法
2015/04/16 Javascript
JS/Jquery判断对象为空的方法
2015/06/11 Javascript
jQuery插件开发汇总
2016/05/15 Javascript
深入理解JS DOM事件机制
2016/08/06 Javascript
原生js的RSA和AES加密解密算法
2016/10/08 Javascript
bootstrap下拉列表与输入框组结合的样式调整
2016/10/08 Javascript
全面解析node 表单的图片上传
2016/11/21 Javascript
纯javascript版日历控件
2016/11/24 Javascript
JS实现的二叉树算法完整实例
2017/04/06 Javascript
使用vue2.0创建的项目的步骤方法
2018/09/25 Javascript
vue-router判断页面未登录自动跳转到登录页的方法示例
2018/11/04 Javascript
JavaScript对象原型链原理解析
2020/01/22 Javascript
vue实现登录、注册、退出、跳转等功能
2020/12/23 Vue.js
python计算文本文件行数的方法
2015/07/06 Python
Django之全局使用request.user.username的实例详解
2020/05/14 Python
Python爬虫爬取糗事百科段子实例分享
2020/07/31 Python
Chemist Warehouse官方海外旗舰店:澳洲第一连锁大药房
2017/08/25 全球购物
个人对照检查材料
2014/02/12 职场文书
商学院大学生求职的自我评价
2014/03/12 职场文书
最经典的商业地产项目广告词
2014/03/13 职场文书