说说JSON和JSONP,也许你会豁然开朗

转载地址:说说JSON和JSONP,也许你会豁然开朗 前言   由于Senc 前言   由于Sencha Touch 2这种开发模式的特性,基本决定了它原生的数据交互行为几乎只能通过AJAX来实现。   当然了,通过调用强大的PhoneGap插件然后打包,你可以实现100%的Socket通讯和本地数据库功能,又或者通过HTML5的WebSocket也可以实现与服务器的通讯和服务端推功能,但

大家好,又见面了,我是全栈君。

转载地址:说说JSON和JSONP,也许你会豁然开朗
前言
  由于Senc
前言
  由于Sencha Touch 2这种开发模式的特性,基本决定了它原生的数据交互行为几乎只能通过AJAX来实现。
  当然了,通过调用强大的PhoneGap插件然后打包,你可以实现100%的Socket通讯和本地数据库功能,又或者通过HTML5的WebSocket也可以实现与服务器的通讯和服务端推功能,但这两种方式都有其局限性,前者需要PhoneGap支持,后者要求用户设备必须支持WebSocket,因此都不能算是ST2的原生解决方案,原生的只有AJAX。
  说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求如何解决?这两个问题目前都有不同的解决方案,比如数据可以用自定义字符串或者用XML来描述,跨域可以通过服务器端代理来解决。
  但到目前为止最被推崇或者说首选的方案还是用JSON来传数据,靠JSONP来跨域。而这就是本文将要讲述的内容。
  JSON(JavaScript Object Notation)和JSONP(JSON with Padding)虽然只有一个字母的差别,但其实他们根本不是一回事儿:JSON是一种数据交换格式,而JSONP是一种依靠开发人员的聪明才智创造出的一种非官方跨域数据交互协议。我们拿最近比较火的谍战片来打个比方,JSON是地下党们用来书写和交换情报的“暗号”,而JSONP则是把用暗号书写的情报传递给自己同志时使用的接头方式。看到没?一个是描述信息的格式,一个是信息传递双方约定的方法。
  既然随便聊聊,那我们就不再采用教条的方式来讲述,而是把关注重心放在帮助开发人员理解是否应当选择使用以及如何使用上。
  什么是JSON
  前面简单说了一下,JSON是一种基于文本的数据交换方式,或者叫做数据描述格式,你是否该选用他首先肯定要关注它所拥有的优点。
  JSON的优点:
  1、基于纯文本,跨平台传递极其简单;
  2、Javascript原生支持,后台语言几乎全部支持;
  3、轻量级数据格式,占用字符数量极少,特别适合互联网传递;
  4、可读性较强,虽然比不上XML那么一目了然,但在合理的依次缩进之后还是很容易识别的;
  5、容易编写和解析,当然前提是你要知道数据结构;
  JSON的缺点当然也有,但在作者看来实在是无关紧要的东西,所以不再单独说明。
  JSON的格式或者叫规则:
  JSON能够以非常简单的方式来描述数据结构,XML能做的它都能做,因此在跨平台方面两者完全不分伯仲。
  1、JSON只有两种数据类型描述符,大括号{}和方括号[],其余英文冒号:是映射符,英文逗号,是分隔符,英文双引号”“是定义符。
  2、大括号{}用来描述一组“不同类型的无序键值对集合”(每个键值对可以理解为OOP的属性描述),方括号[]用来描述一组“相同类型的有序数据集合”(可对应OOP的数组)。
  3、上述两种集合中若有多个子项,则通过英文逗号,进行分隔。
  4、键值对以英文冒号:进行分隔,并且建议键名都加上英文双引号””,以便于不同语言的解析。
  5、JSON内部常用数据类型无非就是字符串、数字、布尔、日期、null 这么几个,字符串必须用双引号引起来,其余的都不用,日期类型比较特殊,这里就不展开讲述了,只是建议如果客户端没有按日期排序功能需求的话,那么把日期时间直接作为字符串传递就好,可以省去很多麻烦。
  JSON实例:
// 描述一个人
var person = {
“Name”: “Bob”,
“Age”: 32,
“Company”: “IBM”,
“Engineer”: true
}

// 获取这个人的信息
var personAge = person.Age;

// 描述几个人
var members = [
{
“Name”: “Bob”,
“Age”: 32,
“Company”: “IBM”,
“Engineer”: true
},
{
“Name”: “John”,
“Age”: 20,
“Company”: “Oracle”,
“Engineer”: false
},
{
“Name”: “Henry”,
“Age”: 45,
“Company”: “Microsoft”,
“Engineer”: false
}
]

// 读取其中John的公司名称
var johnsCompany = members[1].Company;

// 描述一次会议
var conference = {
“Conference”: “Future Marketing”,
“Date”: “2012-6-1”,
“Address”: “Beijing”,
“Members”:
[
{
“Name”: “Bob”,
“Age”: 32,
“Company”: “IBM”,
“Engineer”: true
},
{
“Name”: “John”,
“Age”: 20,
“Company”: “Oracle”,
“Engineer”: false
},
{
“Name”: “Henry”,
“Age”: 45,
“Company”: “Microsoft”,
“Engineer”: false
}
]
}

// 读取参会者Henry是否工程师
var henryIsAnEngineer = conference.Members[2].Engineer;
  关于JSON,就说这么多,更多细节请在开发过程中查阅资料深入学习。
  什么是JSONP
  先说说JSONP是怎么产生的:
  其实网上关于JSONP的讲解有很多,但却千篇一律,而且云里雾里,对于很多刚接触的人来讲理解起来有些困难,小可不才,试着用自己的方式来阐释一下这个问题,看看是否有帮助。
  1、一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准;
  2、不过我们又发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如、、>&#65289;&#65307; <br/>&#10;&#12288;&#12288;3&#12289;&#20110;&#26159;&#21487;&#20197;&#21028;&#26029;&#65292;&#24403;&#21069;&#38454;&#27573;&#22914;&#26524;&#24819;&#36890;&#36807;&#32431;web&#31471;&#65288;ActiveX&#25511;&#20214;&#12289;&#26381;&#21153;&#31471;&#20195;&#29702;&#12289;&#23646;&#20110;&#26410;&#26469;&#30340;HTML5&#20043;Websocket&#31561;&#26041;&#24335;&#19981;&#31639;&#65289;&#36328;&#22495;&#35775;&#38382;&#25968;&#25454;&#23601;&#21482;&#26377;&#19968;&#31181;&#21487;&#33021;&#65292;&#37027;&#23601;&#26159;&#22312;&#36828;&#31243;&#26381;&#21153;&#22120;&#19978;&#35774;&#27861;&#25226;&#25968;&#25454;&#35013;&#36827;js&#26684;&#24335;&#30340;&#25991;&#20214;&#37324;&#65292;&#20379;&#23458;&#25143;&#31471;&#35843;&#29992;&#21644;&#36827;&#19968;&#27493;&#22788;&#29702;&#65307; <br/>&#10;&#12288;&#12288;4&#12289;&#24688;&#24039;&#25105;&#20204;&#24050;&#32463;&#30693;&#36947;&#26377;&#19968;&#31181;&#21483;&#20570;JSON&#30340;&#32431;&#23383;&#31526;&#25968;&#25454;&#26684;&#24335;&#21487;&#20197;&#31616;&#27905;&#30340;&#25551;&#36848;&#22797;&#26434;&#25968;&#25454;&#65292;&#26356;&#22937;&#30340;&#26159;JSON&#36824;&#34987;js&#21407;&#29983;&#25903;&#25345;&#65292;&#25152;&#20197;&#22312;&#23458;&#25143;&#31471;&#20960;&#20046;&#21487;&#20197;&#38543;&#24515;&#25152;&#27442;&#30340;&#22788;&#29702;&#36825;&#31181;&#26684;&#24335;&#30340;&#25968;&#25454;&#65307; <br/>&#10;&#12288;&#12288;5&#12289;&#36825;&#26679;&#23376;&#35299;&#20915;&#26041;&#26696;&#23601;&#21628;&#20043;&#27442;&#20986;&#20102;&#65292;web&#23458;&#25143;&#31471;&#36890;&#36807;&#19982;&#35843;&#29992;&#33050;&#26412;&#19968;&#27169;&#19968;&#26679;&#30340;&#26041;&#24335;&#65292;&#26469;&#35843;&#29992;&#36328;&#22495;&#26381;&#21153;&#22120;&#19978;&#21160;&#24577;&#29983;&#25104;&#30340;js&#26684;&#24335;&#25991;&#20214;&#65288;&#19968;&#33324;&#20197;JSON&#20026;&#21518;&#32512;&#65289;&#65292;&#26174;&#32780;&#26131;&#35265;&#65292;&#26381;&#21153;&#22120;&#20043;&#25152;&#20197;&#35201;&#21160;&#24577;&#29983;&#25104;JSON&#25991;&#20214;&#65292;&#30446;&#30340;&#23601;&#22312;&#20110;&#25226;&#23458;&#25143;&#31471;&#38656;&#35201;&#30340;&#25968;&#25454;&#35013;&#20837;&#36827;&#21435;&#12290; <br/>&#10;&#12288;&#12288;6&#12289;&#23458;&#25143;&#31471;&#22312;&#23545;JSON&#25991;&#20214;&#35843;&#29992;&#25104;&#21151;&#20043;&#21518;&#65292;&#20063;&#23601;&#33719;&#24471;&#20102;&#33258;&#24049;&#25152;&#38656;&#30340;&#25968;&#25454;&#65292;&#21097;&#19979;&#30340;&#23601;&#26159;&#25353;&#29031;&#33258;&#24049;&#38656;&#27714;&#36827;&#34892;&#22788;&#29702;&#21644;&#23637;&#29616;&#20102;&#65292;&#36825;&#31181;&#33719;&#21462;&#36828;&#31243;&#25968;&#25454;&#30340;&#26041;&#24335;&#30475;&#36215;&#26469;&#38750;&#24120;&#20687;AJAX&#65292;&#20294;&#20854;&#23454;&#24182;&#19981;&#19968;&#26679;&#12290; <br/>&#10;&#12288;&#12288;7&#12289;&#20026;&#20102;&#20415;&#20110;&#23458;&#25143;&#31471;&#20351;&#29992;&#25968;&#25454;&#65292;&#36880;&#28176;&#24418;&#25104;&#20102;&#19968;&#31181;&#38750;&#27491;&#24335;&#20256;&#36755;&#21327;&#35758;&#65292;&#20154;&#20204;&#25226;&#23427;&#31216;&#20316;JSONP&#65292;&#35813;&#21327;&#35758;&#30340;&#19968;&#20010;&#35201;&#28857;&#23601;&#26159;&#20801;&#35768;&#29992;&#25143;&#20256;&#36882;&#19968;&#20010;callback&#21442;&#25968;&#32473;&#26381;&#21153;&#31471;&#65292;&#28982;&#21518;&#26381;&#21153;&#31471;&#36820;&#22238;&#25968;&#25454;&#26102;&#20250;&#23558;&#36825;&#20010;callback&#21442;&#25968;&#20316;&#20026;&#20989;&#25968;&#21517;&#26469;&#21253;&#35065;&#20303;JSON&#25968;&#25454;&#65292;&#36825;&#26679;&#23458;&#25143;&#31471;&#23601;&#21487;&#20197;&#38543;&#24847;&#23450;&#21046;&#33258;&#24049;&#30340;&#20989;&#25968;&#26469;&#33258;&#21160;&#22788;&#29702;&#36820;&#22238;&#25968;&#25454;&#20102;&#12290; <br/>&#10;&#12288;&#12288;&#22914;&#26524;&#23545;&#20110;callback&#21442;&#25968;&#22914;&#20309;&#20351;&#29992;&#36824;&#26377;&#20123;&#27169;&#31946;&#30340;&#35805;&#65292;&#25105;&#20204;&#21518;&#38754;&#20250;&#26377;&#20855;&#20307;&#30340;&#23454;&#20363;&#26469;&#35762;&#35299;&#12290; <br/>&#10;&#12288;&#12288;JSONP&#30340;&#23458;&#25143;&#31471;&#20855;&#20307;&#23454;&#29616;&#65306; <br/>&#10;&#12288;&#12288;&#19981;&#31649;jQuery&#20063;&#22909;&#65292;ExtJs&#20063;&#32610;&#65292;&#21448;&#25110;&#32773;&#26159;&#20854;&#20182;&#25903;&#25345;jsonp&#30340;&#26694;&#26550;&#65292;&#20182;&#20204;&#24149;&#21518;&#25152;&#20570;&#30340;&#24037;&#20316;&#37117;&#26159;&#19968;&#26679;&#30340;&#65292;&#19979;&#38754;&#25105;&#26469;&#24490;&#24207;&#28176;&#36827;&#30340;&#35828;&#26126;&#19968;&#19979;jsonp&#22312;&#23458;&#25143;&#31471;&#30340;&#23454;&#29616;&#65306; <br/>&#10;&#12288;&#12288;1&#12289;&#25105;&#20204;&#30693;&#36947;&#65292;&#21738;&#24597;&#36328;&#22495;js&#25991;&#20214;&#20013;&#30340;&#20195;&#30721;&#65288;&#24403;&#28982;&#25351;&#31526;&#21512;web&#33050;&#26412;&#23433;&#20840;&#31574;&#30053;&#30340;&#65289;&#65292;web&#39029;&#38754;&#20063;&#26159;&#21487;&#20197;&#26080;&#26465;&#20214;&#25191;&#34892;&#30340;&#12290; <br/>&#10;&#12288;&#12288;&#36828;&#31243;&#26381;&#21153;&#22120;remoteserver.com&#26681;&#30446;&#24405;&#19979;&#26377;&#20010;remote.js&#25991;&#20214;&#20195;&#30721;&#22914;&#19979;&#65306; <br/>&#10;alert(‘&#25105;&#26159;&#36828;&#31243;&#25991;&#20214;’); <br/>&#10;&#12288;&#12288;&#26412;&#22320;&#26381;&#21153;&#22120;localserver.com&#19979;&#26377;&#20010;jsonp.html&#39029;&#38754;&#20195;&#30721;&#22914;&#19979;&#65306; <br/>&#10; <br/>&#10; <br/>&#10; <br/>&#10; <br/>&#10; <br/>&#10; <br/>&#10;

  毫无疑问,页面将会弹出一个提示窗体,显示跨域调用成功。
  2、现在我们在jsonp.html页面定义一个函数,然后在远程remote.js中传入数据进行调用。
  jsonp.html页面代码如下:

var localHandler = function(data){
alert(‘我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:’ + data.result);
};

  remote.js文件代码如下:
localHandler({“result”:”我是远程js带来的数据”});
  运行之后查看结果,页面成功弹出提示窗口,显示本地函数被跨域的远程js调用成功,并且还接收到了远程js带来的数据。很欣喜,跨域远程获取数据的目的基本实现了,但是又一个问题出现了,我怎么让远程js知道它应该调用的本地函数叫什么名字呢?毕竟是jsonp的服务者都要面对很多服务对象,而这些服务对象各自的本地函数都不相同啊?我们接着往下看。
  3、聪明的开发者很容易想到,只要服务端提供的js脚本是动态生成的就行了呗,这样调用者可以传一个参数过去告诉服务端“我想要一段调用XXX函数的js代码,请你返回给我”,于是服务器就可以按照客户端的需求来生成js脚本并响应了。
  看jsonp.html页面的代码:

// 得到航班信息查询结果后的回调函数
var flightHandler = function(data){
alert(‘你查询的航班结果是:票价 ‘ + data.price + ‘ 元,’ + ‘余票 ‘ + data.tickets + ‘ 张。’);
};
// 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
var url = “http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler“;
// 创建script标签,设置其属性
var script = document.createElement(‘script’);
script.setAttribute(‘src’, url);
// 把script标签加入head,此时调用开始
document.getElementsByTagName(‘head’)[0].appendChild(script);

  这次的代码变化比较大,不再直接把远程js文件写死,而是编码实现动态查询,而这也正是jsonp客户端实现的核心部分,本例中的重点也就在于如何完成jsonp调用的全过程。
  我们看到调用的url中传递了一个code参数,告诉服务器我要查的是CA1998次航班的信息,而callback参数则告诉服务器,我的本地回调函数叫做flightHandler,所以请把查询结果传入这个函数中进行调用。
  OK,服务器很聪明,这个叫做flightResult.aspx的页面生成了一段这样的代码提供给jsonp.html(服务端的实现这里就不演示了,与你选用的语言无关,说到底就是拼接字符串):
flightHandler({
“code”: “CA1998”,
“price”: 1780,
“tickets”: 5
});
  我们看到,传递给flightHandler函数的是一个json,它描述了航班的基本信息。运行一下页面,成功弹出提示窗口,jsonp的执行全过程顺利完成!
  4、到这里为止的话,相信你已经能够理解jsonp的客户端实现原理了吧?剩下的就是如何把代码封装一下,以便于与用户界面交互,从而实现多次和重复调用。
  什么?你用的是jQuery,想知道jQuery如何实现jsonp调用?好吧,那我就好人做到底,再给你一段jQuery使用jsonp的代码(我们依然沿用上面那个航班信息查询的例子,假定返回jsonp结果不变):

Untitled Page

jQuery(document).ready(function(){
$.ajax({
type: “get”,
async: false,
url: “http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998“,
dataType: “jsonp”,
jsonp: “callback”,//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:”flightHandler”,//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写”?”,jQuery会自动为你处理数据
success: function(json){
alert(‘您查询到航班信息:票价: ‘ + json.price + ‘ 元,余票: ‘ + json.tickets + ‘ 张。’);
},
error: function(){
alert(‘fail’);
}
});
});

  是不是有点奇怪?为什么我这次没有写flightHandler这个函数呢?而且竟然也运行成功了!哈哈,这就是jQuery的功劳了,jquery在处理jsonp类型的ajax时(还是忍不住吐槽,虽然jquery也把jsonp归入了ajax,但其实它们真的不是一回事儿),自动帮你生成回调函数并把数据取出来供success属性方法来调用,是不是很爽呀?
  好啦,写到这里,我已经无力再写下去,又困又累,得赶紧睡觉。朋友们要是看这不错,觉得有启发,给点个“推荐”呗!由于实在比较简单,所以就不再提供demo源码下载了。
  没想到上了博客园的头条推荐。看到大家对这篇文章的认可和评论,还是很开心的,这里针对ajax与jsonp的异同再做一些补充说明:
  4月20日下午补充
  1、ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;
  2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加标签来调用服务器提供的js脚本。
  3、所以说,其实ajax与jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,jsonp本身也不排斥同域的数据的获取。
  4、还有就是,jsonp是一种方式或者说非强制性协议,如同ajax一样,它也不一定非要用json格式来传递数据,如果你愿意,字符串都行,只不过这样不利于用jsonp提供公开服务。
  总而言之,jsonp不是ajax的一个特例,哪怕jquery等巨头把jsonp封装进了ajax,也不能改变这一点!
ha Touch 2这种开发模式的特性,基本决定了它原生的数据交互行为几乎只能通过AJAX来实现。
  当然了,通过调用强大的PhoneGap插件然后打包,你可以实现100%的Socket通讯和本地数据库功能,又或者通过HTML5的WebSocket也可以实现与服务器的通讯和服务端推功能,但这两种方式都有其局限性,前者需要PhoneGap支持,后者要求用户设备必须支持WebSocket,因此都不能算是ST2的原生解决方案,原生的只有AJAX。
  说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求如何解决?这两个问题目前都有不同的解决方案,比如数据可以用自定义字符串或者用XML来描述,跨域可以通过服务器端代理来解决。
  但到目前为止最被推崇或者说首选的方案还是用JSON来传数据,靠JSONP来跨域。而这就是本文将要讲述的内容。
  JSON(JavaScript Object Notation)和JSONP(JSON with Padding)虽然只有一个字母的差别,但其实他们根本不是一回事儿:JSON是一种数据交换格式,而JSONP是一种依靠开发人员的聪明才智创造出的一种非官方跨域数据交互协议。我们拿最近比较火的谍战片来打个比方,JSON是地下党们用来书写和交换情报的“暗号”,而JSONP则是把用暗号书写的情报传递给自己同志时使用的接头方式。看到没?一个是描述信息的格式,一个是信息传递双方约定的方法。
  既然随便聊聊,那我们就不再采用教条的方式来讲述,而是把关注重心放在帮助开发人员理解是否应当选择使用以及如何使用上。
  什么是JSON
  前面简单说了一下,JSON是一种基于文本的数据交换方式,或者叫做数据描述格式,你是否该选用他首先肯定要关注它所拥有的优点。
  JSON的优点:
  1、基于纯文本,跨平台传递极其简单;
  2、Javascript原生支持,后台语言几乎全部支持;
  3、轻量级数据格式,占用字符数量极少,特别适合互联网传递;
  4、可读性较强,虽然比不上XML那么一目了然,但在合理的依次缩进之后还是很容易识别的;
  5、容易编写和解析,当然前提是你要知道数据结构;
  JSON的缺点当然也有,但在作者看来实在是无关紧要的东西,所以不再单独说明。
  JSON的格式或者叫规则:
  JSON能够以非常简单的方式来描述数据结构,XML能做的它都能做,因此在跨平台方面两者完全不分伯仲。
  1、JSON只有两种数据类型描述符,大括号{}和方括号[],其余英文冒号:是映射符,英文逗号,是分隔符,英文双引号”“是定义符。
  2、大括号{}用来描述一组“不同类型的无序键值对集合”(每个键值对可以理解为OOP的属性描述),方括号[]用来描述一组“相同类型的有序数据集合”(可对应OOP的数组)。
  3、上述两种集合中若有多个子项,则通过英文逗号,进行分隔。
  4、键值对以英文冒号:进行分隔,并且建议键名都加上英文双引号””,以便于不同语言的解析。
  5、JSON内部常用数据类型无非就是字符串、数字、布尔、日期、null 这么几个,字符串必须用双引号引起来,其余的都不用,日期类型比较特殊,这里就不展开讲述了,只是建议如果客户端没有按日期排序功能需求的话,那么把日期时间直接作为字符串传递就好,可以省去很多麻烦。
  JSON实例:
// 描述一个人
var person = {
“Name”: “Bob”,
“Age”: 32,
“Company”: “IBM”,
“Engineer”: true
}

// 获取这个人的信息
var personAge = person.Age;

// 描述几个人
var members = [
{
“Name”: “Bob”,
“Age”: 32,
“Company”: “IBM”,
“Engineer”: true
},
{
“Name”: “John”,
“Age”: 20,
“Company”: “Oracle”,
“Engineer”: false
},
{
“Name”: “Henry”,
“Age”: 45,
“Company”: “Microsoft”,
“Engineer”: false
}
]

// 读取其中John的公司名称
var johnsCompany = members[1].Company;

// 描述一次会议
var conference = {
“Conference”: “Future Marketing”,
“Date”: “2012-6-1”,
“Address”: “Beijing”,
“Members”:
[
{
“Name”: “Bob”,
“Age”: 32,
“Company”: “IBM”,
“Engineer”: true
},
{
“Name”: “John”,
“Age”: 20,
“Company”: “Oracle”,
“Engineer”: false
},
{
“Name”: “Henry”,
“Age”: 45,
“Company”: “Microsoft”,
“Engineer”: false
}
]
}

// 读取参会者Henry是否工程师
var henryIsAnEngineer = conference.Members[2].Engineer;
  关于JSON,就说这么多,更多细节请在开发过程中查阅资料深入学习。
  什么是JSONP
  先说说JSONP是怎么产生的:
  其实网上关于JSONP的讲解有很多,但却千篇一律,而且云里雾里,对于很多刚接触的人来讲理解起来有些困难,小可不才,试着用自己的方式来阐释一下这个问题,看看是否有帮助。
  1、一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准;
  2、不过我们又发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如、、>&#65289;&#65307; <br/>&#10;&#12288;&#12288;3&#12289;&#20110;&#26159;&#21487;&#20197;&#21028;&#26029;&#65292;&#24403;&#21069;&#38454;&#27573;&#22914;&#26524;&#24819;&#36890;&#36807;&#32431;web&#31471;&#65288;ActiveX&#25511;&#20214;&#12289;&#26381;&#21153;&#31471;&#20195;&#29702;&#12289;&#23646;&#20110;&#26410;&#26469;&#30340;HTML5&#20043;Websocket&#31561;&#26041;&#24335;&#19981;&#31639;&#65289;&#36328;&#22495;&#35775;&#38382;&#25968;&#25454;&#23601;&#21482;&#26377;&#19968;&#31181;&#21487;&#33021;&#65292;&#37027;&#23601;&#26159;&#22312;&#36828;&#31243;&#26381;&#21153;&#22120;&#19978;&#35774;&#27861;&#25226;&#25968;&#25454;&#35013;&#36827;js&#26684;&#24335;&#30340;&#25991;&#20214;&#37324;&#65292;&#20379;&#23458;&#25143;&#31471;&#35843;&#29992;&#21644;&#36827;&#19968;&#27493;&#22788;&#29702;&#65307; <br/>&#10;&#12288;&#12288;4&#12289;&#24688;&#24039;&#25105;&#20204;&#24050;&#32463;&#30693;&#36947;&#26377;&#19968;&#31181;&#21483;&#20570;JSON&#30340;&#32431;&#23383;&#31526;&#25968;&#25454;&#26684;&#24335;&#21487;&#20197;&#31616;&#27905;&#30340;&#25551;&#36848;&#22797;&#26434;&#25968;&#25454;&#65292;&#26356;&#22937;&#30340;&#26159;JSON&#36824;&#34987;js&#21407;&#29983;&#25903;&#25345;&#65292;&#25152;&#20197;&#22312;&#23458;&#25143;&#31471;&#20960;&#20046;&#21487;&#20197;&#38543;&#24515;&#25152;&#27442;&#30340;&#22788;&#29702;&#36825;&#31181;&#26684;&#24335;&#30340;&#25968;&#25454;&#65307; <br/>&#10;&#12288;&#12288;5&#12289;&#36825;&#26679;&#23376;&#35299;&#20915;&#26041;&#26696;&#23601;&#21628;&#20043;&#27442;&#20986;&#20102;&#65292;web&#23458;&#25143;&#31471;&#36890;&#36807;&#19982;&#35843;&#29992;&#33050;&#26412;&#19968;&#27169;&#19968;&#26679;&#30340;&#26041;&#24335;&#65292;&#26469;&#35843;&#29992;&#36328;&#22495;&#26381;&#21153;&#22120;&#19978;&#21160;&#24577;&#29983;&#25104;&#30340;js&#26684;&#24335;&#25991;&#20214;&#65288;&#19968;&#33324;&#20197;JSON&#20026;&#21518;&#32512;&#65289;&#65292;&#26174;&#32780;&#26131;&#35265;&#65292;&#26381;&#21153;&#22120;&#20043;&#25152;&#20197;&#35201;&#21160;&#24577;&#29983;&#25104;JSON&#25991;&#20214;&#65292;&#30446;&#30340;&#23601;&#22312;&#20110;&#25226;&#23458;&#25143;&#31471;&#38656;&#35201;&#30340;&#25968;&#25454;&#35013;&#20837;&#36827;&#21435;&#12290; <br/>&#10;&#12288;&#12288;6&#12289;&#23458;&#25143;&#31471;&#22312;&#23545;JSON&#25991;&#20214;&#35843;&#29992;&#25104;&#21151;&#20043;&#21518;&#65292;&#20063;&#23601;&#33719;&#24471;&#20102;&#33258;&#24049;&#25152;&#38656;&#30340;&#25968;&#25454;&#65292;&#21097;&#19979;&#30340;&#23601;&#26159;&#25353;&#29031;&#33258;&#24049;&#38656;&#27714;&#36827;&#34892;&#22788;&#29702;&#21644;&#23637;&#29616;&#20102;&#65292;&#36825;&#31181;&#33719;&#21462;&#36828;&#31243;&#25968;&#25454;&#30340;&#26041;&#24335;&#30475;&#36215;&#26469;&#38750;&#24120;&#20687;AJAX&#65292;&#20294;&#20854;&#23454;&#24182;&#19981;&#19968;&#26679;&#12290; <br/>&#10;&#12288;&#12288;7&#12289;&#20026;&#20102;&#20415;&#20110;&#23458;&#25143;&#31471;&#20351;&#29992;&#25968;&#25454;&#65292;&#36880;&#28176;&#24418;&#25104;&#20102;&#19968;&#31181;&#38750;&#27491;&#24335;&#20256;&#36755;&#21327;&#35758;&#65292;&#20154;&#20204;&#25226;&#23427;&#31216;&#20316;JSONP&#65292;&#35813;&#21327;&#35758;&#30340;&#19968;&#20010;&#35201;&#28857;&#23601;&#26159;&#20801;&#35768;&#29992;&#25143;&#20256;&#36882;&#19968;&#20010;callback&#21442;&#25968;&#32473;&#26381;&#21153;&#31471;&#65292;&#28982;&#21518;&#26381;&#21153;&#31471;&#36820;&#22238;&#25968;&#25454;&#26102;&#20250;&#23558;&#36825;&#20010;callback&#21442;&#25968;&#20316;&#20026;&#20989;&#25968;&#21517;&#26469;&#21253;&#35065;&#20303;JSON&#25968;&#25454;&#65292;&#36825;&#26679;&#23458;&#25143;&#31471;&#23601;&#21487;&#20197;&#38543;&#24847;&#23450;&#21046;&#33258;&#24049;&#30340;&#20989;&#25968;&#26469;&#33258;&#21160;&#22788;&#29702;&#36820;&#22238;&#25968;&#25454;&#20102;&#12290; <br/>&#10;&#12288;&#12288;&#22914;&#26524;&#23545;&#20110;callback&#21442;&#25968;&#22914;&#20309;&#20351;&#29992;&#36824;&#26377;&#20123;&#27169;&#31946;&#30340;&#35805;&#65292;&#25105;&#20204;&#21518;&#38754;&#20250;&#26377;&#20855;&#20307;&#30340;&#23454;&#20363;&#26469;&#35762;&#35299;&#12290; <br/>&#10;&#12288;&#12288;JSONP&#30340;&#23458;&#25143;&#31471;&#20855;&#20307;&#23454;&#29616;&#65306; <br/>&#10;&#12288;&#12288;&#19981;&#31649;jQuery&#20063;&#22909;&#65292;ExtJs&#20063;&#32610;&#65292;&#21448;&#25110;&#32773;&#26159;&#20854;&#20182;&#25903;&#25345;jsonp&#30340;&#26694;&#26550;&#65292;&#20182;&#20204;&#24149;&#21518;&#25152;&#20570;&#30340;&#24037;&#20316;&#37117;&#26159;&#19968;&#26679;&#30340;&#65292;&#19979;&#38754;&#25105;&#26469;&#24490;&#24207;&#28176;&#36827;&#30340;&#35828;&#26126;&#19968;&#19979;jsonp&#22312;&#23458;&#25143;&#31471;&#30340;&#23454;&#29616;&#65306; <br/>&#10;&#12288;&#12288;1&#12289;&#25105;&#20204;&#30693;&#36947;&#65292;&#21738;&#24597;&#36328;&#22495;js&#25991;&#20214;&#20013;&#30340;&#20195;&#30721;&#65288;&#24403;&#28982;&#25351;&#31526;&#21512;web&#33050;&#26412;&#23433;&#20840;&#31574;&#30053;&#30340;&#65289;&#65292;web&#39029;&#38754;&#20063;&#26159;&#21487;&#20197;&#26080;&#26465;&#20214;&#25191;&#34892;&#30340;&#12290; <br/>&#10;&#12288;&#12288;&#36828;&#31243;&#26381;&#21153;&#22120;remoteserver.com&#26681;&#30446;&#24405;&#19979;&#26377;&#20010;remote.js&#25991;&#20214;&#20195;&#30721;&#22914;&#19979;&#65306; <br/>&#10;alert(‘&#25105;&#26159;&#36828;&#31243;&#25991;&#20214;’); <br/>&#10;&#12288;&#12288;&#26412;&#22320;&#26381;&#21153;&#22120;localserver.com&#19979;&#26377;&#20010;jsonp.html&#39029;&#38754;&#20195;&#30721;&#22914;&#19979;&#65306; <br/>&#10; <br/>&#10; <br/>&#10; <br/>&#10; <br/>&#10; <br/>&#10; <br/>&#10;

  毫无疑问,页面将会弹出一个提示窗体,显示跨域调用成功。
  2、现在我们在jsonp.html页面定义一个函数,然后在远程remote.js中传入数据进行调用。
  jsonp.html页面代码如下:

var localHandler = function(data){
alert(‘我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:’ + data.result);
};

  remote.js文件代码如下:
localHandler({“result”:”我是远程js带来的数据”});
  运行之后查看结果,页面成功弹出提示窗口,显示本地函数被跨域的远程js调用成功,并且还接收到了远程js带来的数据。很欣喜,跨域远程获取数据的目的基本实现了,但是又一个问题出现了,我怎么让远程js知道它应该调用的本地函数叫什么名字呢?毕竟是jsonp的服务者都要面对很多服务对象,而这些服务对象各自的本地函数都不相同啊?我们接着往下看。
  3、聪明的开发者很容易想到,只要服务端提供的js脚本是动态生成的就行了呗,这样调用者可以传一个参数过去告诉服务端“我想要一段调用XXX函数的js代码,请你返回给我”,于是服务器就可以按照客户端的需求来生成js脚本并响应了。
  看jsonp.html页面的代码:

// 得到航班信息查询结果后的回调函数
var flightHandler = function(data){
alert(‘你查询的航班结果是:票价 ‘ + data.price + ‘ 元,’ + ‘余票 ‘ + data.tickets + ‘ 张。’);
};
// 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
var url = “http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler“;
// 创建script标签,设置其属性
var script = document.createElement(‘script’);
script.setAttribute(‘src’, url);
// 把script标签加入head,此时调用开始
document.getElementsByTagName(‘head’)[0].appendChild(script);

  这次的代码变化比较大,不再直接把远程js文件写死,而是编码实现动态查询,而这也正是jsonp客户端实现的核心部分,本例中的重点也就在于如何完成jsonp调用的全过程。
  我们看到调用的url中传递了一个code参数,告诉服务器我要查的是CA1998次航班的信息,而callback参数则告诉服务器,我的本地回调函数叫做flightHandler,所以请把查询结果传入这个函数中进行调用。
  OK,服务器很聪明,这个叫做flightResult.aspx的页面生成了一段这样的代码提供给jsonp.html(服务端的实现这里就不演示了,与你选用的语言无关,说到底就是拼接字符串):
flightHandler({
“code”: “CA1998”,
“price”: 1780,
“tickets”: 5
});
  我们看到,传递给flightHandler函数的是一个json,它描述了航班的基本信息。运行一下页面,成功弹出提示窗口,jsonp的执行全过程顺利完成!
  4、到这里为止的话,相信你已经能够理解jsonp的客户端实现原理了吧?剩下的就是如何把代码封装一下,以便于与用户界面交互,从而实现多次和重复调用。
  什么?你用的是jQuery,想知道jQuery如何实现jsonp调用?好吧,那我就好人做到底,再给你一段jQuery使用jsonp的代码(我们依然沿用上面那个航班信息查询的例子,假定返回jsonp结果不变):

Untitled Page

jQuery(document).ready(function(){
$.ajax({
type: “get”,
async: false,
url: “http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998“,
dataType: “jsonp”,
jsonp: “callback”,//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:”flightHandler”,//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写”?”,jQuery会自动为你处理数据
success: function(json){
alert(‘您查询到航班信息:票价: ‘ + json.price + ‘ 元,余票: ‘ + json.tickets + ‘ 张。’);
},
error: function(){
alert(‘fail’);
}
});
});

  是不是有点奇怪?为什么我这次没有写flightHandler这个函数呢?而且竟然也运行成功了!哈哈,这就是jQuery的功劳了,jquery在处理jsonp类型的ajax时(还是忍不住吐槽,虽然jquery也把jsonp归入了ajax,但其实它们真的不是一回事儿),自动帮你生成回调函数并把数据取出来供success属性方法来调用,是不是很爽呀?
  好啦,写到这里,我已经无力再写下去,又困又累,得赶紧睡觉。朋友们要是看这不错,觉得有启发,给点个“推荐”呗!由于实在比较简单,所以就不再提供demo源码下载了。
  没想到上了博客园的头条推荐。看到大家对这篇文章的认可和评论,还是很开心的,这里针对ajax与jsonp的异同再做一些补充说明:
  4月20日下午补充
  1、ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;
  2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/121230.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Eclipse+ADT+Android SDK 搭建安卓开发环境「建议收藏」

    Eclipse+ADT+Android SDK 搭建安卓开发环境「建议收藏」Eclipse+ADT+AndroidSDK搭建安卓开发环境要求必备知识windows7基本操作。运行环境windows7(64位); eclipse-jee-luna-

  • 好东西!

    好东西!

  • vim 复制粘贴「建议收藏」

    vim 复制粘贴「建议收藏」VIM编辑器1.复制和粘贴整行我们都知道复制的快捷键是“nyy”,粘贴的快捷键是“p”。Tips1.“yy”是复制光标所在行,“nyy”是复制包括光标所在行以及向下的“n-1”行**,一共n行。2.“p”是将已经复制的数据,粘贴在光标所在行的下一行。“P”为粘贴在光标所在行的上一行。2.粘贴和复制一个单词当我们想粘贴一行数据中的某些单词时有一些快捷键如下:yw 复制一个单词(包括单词后面的空白字符)4yl 复制当前光标下的字符、以及后面三个字符,总共四个字符4yh 复制光标前面

  • 图像伽马校正_自适应伽马矫正matlab

    图像伽马校正_自适应伽马矫正matlabGamma矫正颜色空间(具体内容在之前的文章有讲)sRGB

  • 使用postman发送http请求

    使用postman发送http请求

  • CentOS7离线安装gcc

    CentOS7离线安装gcc安装Redis时,需要使用gcc。如果系统是联网的,那么直接使用如下命令联网安装。yum-yinstallgcc但是如果系统不可联网,那么就需要一种离线安装的方式了。步骤如下:1.从CentOS7的系统安装镜像中取出需要的rpm包(也可以通过别的方式获取):解压镜像文件,进入"Packages"目录,里面很多rpm包,取出如下几个:mpfr-3.1.1-4.el7….

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号