Ajax跨域请求解决方案——jsonp

转自:http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html

1、一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准;

2、不过我们又发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>);

3、于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理;

4、恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据;

5、这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。

6、客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但其实并不一样。

7、为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

如果对于callback参数如何使用还有些模糊的话,我们后面会有具体的实例来讲解。

JSONP的客户端具体实现:

不管jQuery也好,extjs也罢,又或者是其他支持jsonp的框架,他们幕后所做的工作都是一样的,下面我来循序渐进的说明一下jsonp在客户端的实现:

 

1、我们知道,哪怕跨域js文件中的代码(当然指符合web脚本安全策略的),web页面也是可以无条件执行的。

远程服务器remoteserver.com根目录下有个remote.js文件代码如下:

alert('我是远程文件');

本地服务器localserver.com下有个jsonp.html页面代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title></title><script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body></body>
</html>

毫无疑问,页面将会弹出一个提示窗体,显示跨域调用成功。

 

2、现在我们在jsonp.html页面定义一个函数,然后在远程remote.js中传入数据进行调用。

jsonp.html页面代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title></title><script type="text/javascript">var localHandler = function(data){alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result);};</script><script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body></body>
</html>

运行之后查看结果,页面成功弹出提示窗口,显示本地函数被跨域的远程js调用成功,并且还接收到了远程js带来的数据。很欣喜,跨域远程获取数据的目的基本实现了,但是又一个问题出现了,我怎么让远程js知道它应该调用的本地函数叫什么名字呢?毕竟是jsonp的服务者都要面对很多服务对象,而这些服务对象各自的本地函数都不相同啊?我们接着往下看。

 

3、聪明的开发者很容易想到,只要服务端提供的js脚本是动态生成的就行了呗,这样调用者可以传一个参数过去告诉服务端“我想要一段调用XXX函数的js代码,请你返回给我”,于是服务器就可以按照客户端的需求来生成js脚本并响应了。

看jsonp.html页面的代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title></title><script type="text/javascript">// 得到航班信息查询结果后的回调函数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); </script>
</head>
<body></body>
</html>

这次的代码变化比较大,不再直接把远程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结果不变):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" ><head><title>Untitled Page</title><script type="text/javascript" src=jquery.min.js"></script><script type="text/javascript">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');}});});</script></head><body></body></html>

是不是有点奇怪?为什么我这次没有写flightHandler这个函数呢?而且竟然也运行成功了!哈哈,这就是jQuery的功劳了,jquery在处理jsonp类型的ajax时(还是忍不住吐槽,虽然jquery也把jsonp归入了ajax,但其实它们真的不是一回事儿),自动帮你生成回调函数并把数据取出来供success属性方法来调用,是不是很爽呀?

1、ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;

2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。

3、所以说,其实ajax与jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,jsonp本身也不排斥同域的数据的获取。

4、还有就是,jsonp是一种方式或者说非强制性协议,如同ajax一样,它也不一定非要用json格式来传递数据,如果你愿意,字符串都行,只不过这样不利于用jsonp提供公开服务。

总而言之,jsonp不是ajax的一个特例,哪怕jquery等巨头把jsonp封装进了ajax,也不能改变着一点!

转载于:https://www.cnblogs.com/ccode/p/4871853.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/491747.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MATLAB的Kmeans函数实现聚类

转自https://blog.csdn.net/a493823882/article/details/79282425 使用方法&#xff1a; Idxkmeans(X,K) [Idx,C]kmeans(X,K) [Idx,C,sumD]kmeans(X,K) [Idx,C,sumD,D]kmeans(X,K) […]Kmeans(…,’Param1’,Val1,’Param2’,Val2,…)各输入…

吴恩达《机器学习》学习笔记十一——神经网络代码

吴恩达《机器学习》学习笔记十一——神经网络代码数据准备神经网络结构与代价函数初始化设置反向传播算法训练网络与验证课程链接&#xff1a;https://www.bilibili.com/video/BV164411b7dx?fromsearch&seid5329376196520099118 数据集链接&#xff1a;https://pan.baidu…

中国科研人员发明单晶体管逻辑结构新原理

▲随着晶体管不断缩小特征尺寸&#xff0c;集成电路的性能得以持续提升。然而在超小器件尺寸下&#xff0c;硅材料的物理极限导致了功耗的大幅提升&#xff0c;难以进一步持续减小晶体管的特征尺寸。来源&#xff1a;文汇网通过引入层状半导体&#xff0c;并依据其特性设计新型…

Java 内存模型

1、并发模型编程的分类 在并发模型编程中&#xff0c;我们需要解决两个关键问题&#xff1a;线程之间如何通信以及线程之间如何同步。线程之间的通信包括两种&#xff1a;共享内存和消息传递。 Java并发采用的是共享内存模型。 2、Java内存模型的抽象 Java内存模型的主要目标是…

神经网络中Batch和Epoch之间的区别

来自蜂口知道公众号 随机梯度下降法是一种具有大量超参数的学习算法。通常会使初学者感到困惑的两个超参数: Batch大小和Epoch数量,它们都是整数值&#xff0c;看起来做的事情是一样的。在这篇文章中&#xff0c;您将发现随机梯度下降中Batch和Epoch之间的差异。 阅读这篇文章…

PyTorch框架学习一——PyTorch的安装(CPU版本)

PyTorch框架学习一——PyTorch的安装&#xff08;CPU版本&#xff09;PyTorch简介PyTorch的安装&#xff08;CPU版&#xff09;机器学习/深度学习领域的学习都是需要理论和实践相结合的&#xff0c;而它们的实践都需要借助于一个框架来实现&#xff0c;PyTorch在学术界目前处于…

你的大脑在自动驾驶,而你一无所知

来源&#xff1a;果壳想象一下&#xff0c;你的大脑里有着两个小人&#xff0c;它们在不停地打架&#xff0c;试图夺取控制你行动的权力。当然&#xff0c;这两个小人并不是你善意和邪恶的念头。那它们是什么&#xff1f;在很多人看来&#xff0c;这两者就是我们的意识和无意识…

常用的损失函数

来自 机器学习成长之路公众号 本文将常用的损失函数分为了两大类&#xff1a;分类和回归。然后又分别对这两类进行了细分和讲解&#xff0c;其中回归中包含了一种不太常见的损失函数&#xff1a;平均偏差误差&#xff0c;可以用来确定模型中存在正偏差还是负偏差。 从学习任务…

吴恩达《机器学习》学习笔记十一——应用机器学习的建议

吴恩达《机器学习》学习笔记十一——应用机器学习的建议一、训练完模型后下一步要做什么二、评估算法与模型选择1.训练集与测试集2.训练/测试步骤3.模型选择4.数据集新的划分——验证集的加入三、偏差与方差1.偏差与方差的理解2.正则化和偏差方差的关系3.学习曲线四、决定接下来…

为什么说深耕AI领域绕不开知识图谱?

来源&#xff1a;AI科技大本营“所有在 AI 领域深耕的人&#xff0c;最终都会发现语义鸿沟仍是一个非常具有挑战性的问题&#xff0c;这最终还需要借助知识图谱等技术&#xff0c;来帮助将整体的 AI 认知取得新进展。”在 5 月 26 日的 CTA 峰会机器学习专场&#xff0c;Hulu 首…

Ruby 变量

Ruby 之初体验。接着学习&#xff0c;昨天竟然病了&#xff0c;懈怠了。要坚持锻炼丫&#xff0c;就和坚持写博客似的。 来&#xff0c;下面接着唠。 来侃侃变量&#xff0c;百度上说是能储存计算结果或能表示值抽象概念。顾名思义就是可变化的值。 Ruby 支持五种类型的变量。 …

机器学习中的相似性度量总结

来自 机器学习算法那些事公众号 在做分类时常常需要估算不同样本之间的相似性度量(Similarity Measurement)&#xff0c;这时通常采用的方法就是计算样本间的“距离”(Distance)。采用什么样的方法计算距离是很讲究&#xff0c;甚至关系到分类的正确与否。 目录 1. 欧氏距离 …

吴恩达《机器学习》学习笔记十二——机器学习系统

吴恩达《机器学习》学习笔记十二——机器学习系统一、设计机器学习系统的思想1.快速实现绘制学习曲线——寻找重点优化的方向2.误差分析3.数值估计二、偏斜类问题&#xff08;类别不均衡&#xff09;三、查准率P与召回率R——代替准确率的评估指标四、查准率与召回率的权衡——…

增强现实:一场正在到来的医疗革命

来源&#xff1a; 资本实验室图像化可以让医生的诊断、决策和治疗更加准确&#xff0c;可以说是医疗史上非常重要的一项技术突破。近几年&#xff0c;通讯技术的发展推动了空间计算的快速商业化。在医疗领域&#xff0c;增强现实&#xff08;AR&#xff09;、虚拟现实&#xff…

android user版本默认开启调试模式

由于项目需要&#xff0c;需要发布版本默认开启调试模式&#xff0c;修改方式如下&#xff1a; 1.开启开发者模式 context.getSharedPreferences(DevelopmentSettings.PREF_FILE,Context.MODE_PRIVATE).edit().putBoolean( DevelopmentSettings.PREF_SHOW, true).apply(); 2.勾…

吴恩达《机器学习》学习笔记十三——机器学习系统(补充)

这次笔记是对笔记十二的补充&#xff0c;之前讨论了评价指标&#xff0c;这次主要是补充机器学习系统设计中另一个重要的方面&#xff0c;用来训练的数据有多少的问题。 笔记十二地址&#xff1a;https://blog.csdn.net/qq_40467656/article/details/107602209 之前曾说过不要…

TensorFlow实现简单的卷积网络

使用的数据集是MNIST&#xff0c;下载方法见之前的博客 from tensorflow.examples.tutorials.mnist import input_data import tensorflow as tf mnist input_data.read_data_sets(r"D:\PycharmProjects\tensorflow\MNIST_data", one_hotTrue) sess tf.Interactiv…

BZOJ2819 Nim(DFS序)

题目&#xff1a;单点修改、树链查询。 可以直接用树链剖分做。。 修改是O(QlogN)&#xff0c;查询是O(QlogNlogN)&#xff0c;QN500000&#xff1b; 听说会超时。。 这题也可以用DFS序来做。 先不看修改&#xff0c;单单查询&#xff1a;可以求出每个点到根的xor值&#xff0c…

全球CMOS图像传感器厂商最新排名:黑马杀出

来源&#xff1a;半导体行业观察近期&#xff0c;台湾地区的Yuanta Research发布报告&#xff0c;介绍了其对CMOS图像传感器(CIS)市场的看法&#xff0c;以及到2022年的前景预期。从该研究报告可以看出&#xff0c;2018年全球CMOS图像传感器的市场规模为137亿美元&#xff0c;其…

下载CIFAR-10、CIFAR-100数据集的方法

该网站的数据集目录MNISTCIFAR-10CIFAR-100STL-10SVHNILSVRC2012 task 1 网址&#xff1a;http://rodrigob.github.io/are_we_there_yet/build/classification_datasets_results.html