http://www.g7blogs.com/?p=821

作为一枚前端,提起jsonp大家都不会陌生。特别是在我们组内的业务中,和服务器端交互的数据几乎都是采用这种形式。但假如要让你用原生的JS写出XHR请求来构造JSONP,估计都要跪了吧。因为我们都习惯把jQuery当成了JS的一部分了,就好比平时都是坐飞机到帝都的,你突然说让我骑个单车上北京。不是说不行,只是平时骄奢惯了,适应不了原生态。所以这篇东西要说的并不是那些Google随便一搜就可以搜到的JSONP科普文,而重点要说的是jQuery下处理JSONP的一些坑!槽不多吐,直接去片。

首先我要搭建起一个服务器端的环境,才能继续进行下面的步骤。这个年头,不会点Nodejs都对不起前端开发这个Title,所以我选择了ExpressJS。在前端好基友Webstorm下搭建node服务器就是傻瓜式操作。

搞好服务器环境后,我们分别写两个“JSONP”的API。


在这里看到,两个function分别是jsonp和corejsonp。jsonp是我自己构造的一个方法,这是后面提到的内容重点所在。corejsonp则是Node ExpressJS框架封装好的返回jsonp的接口,用于和前者进行对比。这里我们可以看到第一个方法特别声明了respone的content-type为”text/plain”。下面开始体验:

这里你可能会说,有啥区别呢,两者都能正常工作啊,只是后者在控制台多了个warning的提醒:Resource interpreted as Script but transferred with MIME type text/plain 。这个提示是因为,向JSONP接口发起请求的时候,浏览器期望的响应格式为”text/javascript”或者”application/json”,而实际返回的格式却是”text/plain”,所以MIME type就不匹配了。下面对比感受一下:


可以看到,其实使用框架封装好的jsonp接口返回的是预期的”text/javascript”格式。这是第一种情况,就是服务器端会根据客户端发起的URI中的query而返回对应的callback名称,如下:

但我们日常工作中,经常会遇到的情况就是,服务器端返回的函数名称是固定的,而不是随着请求的URI而同步,这时候MIME Type就开始发挥他的作用了。这次我们将服务器端返回的函数名称固定为callme,再次上图感受一下。



好了,这时候我们看到了亮晶晶的报错了,callme is not defined。而且仔细的你还应该发现,我们在success回调函数里定义的console.info等操作也并没有执行。于是你就想,既然说callme没有定义,那我预先定义一个不也行么?于是就有了下面的一幕:

啊哈,函数再次被成功执行了。于是由于项目时间太赶啦,先上线了再说,剩下的你就没再去深究了。但作为一枚有志青年,岂能就此罢手。我们还是来研究一下为什么会这样子。其实我们看到,这里执行成功的只是预先定义好的callme函数,而不是jQuery里的success回调函数。也就是说,jQuery的这个get请求其实是理解成失败的。然后我们就跑去查一下jQuery的API,发现其中有个jsonpCallback,可以用于自定义回调函数名称,于是又赶紧尝试了一把:

然后发现,控制台有两次输出,第一次是callme函数的执行结果,第二次是success回调的执行结果。然后你又去把之前预先定义的callme删掉运行一次,于是意料之中的,控制台只有一次输出结果,那就是success回调的执行结果。你就想,其实决定jQuery的jsonp请求是否成功的真的是MIME Type么?为了解答你这个疑问,我又跑去把服务端的输出改为”text/javascript”:


咦~~,那个烦人的warning不见了,但一样是输出了两次结果。这时候有没有一种恍然大悟的感觉呢?其实决定jQuery的jsonp请求是否成功关键是服务器返回的函数名是否和jQuery发出去的的函数名是否一致。而服务器返回的响应,无论是什么格式只会影响浏览器的warning。稍等,真的是这样吗?不如我们再来改一改,这次服务器依然是返回json格式,但jsonpCallback和预定义的函数也改名了:

看完这个结果后,我们甚至可以看看返回的MIME Type是image时候的反应,注意这里预定义的函数名和jsonpCallback的名字:

说到这里,我的结论就是:MIME Type并非关键性因素,更重要的是服务器端返回的函数名

以上的测试是不是有种黑盒测试的感觉呢?于是我还尝试去阅读了一下jQuery最新版的关于ajax部分的源码,鉴于技术水平有限,对于代码的理解也不算透彻,只是大概看出个所以然,对于其中一些代码片段也加上了自己所理解的中文注释。有兴趣的小伙伴们可以研究一下,看不懂的也没关系,你要相信你以后再看会看懂的=。=

其实只要记住:JSONP的本质是执行服务器返回的script脚本。

所以下次负责jsonp相关的时候,记得提醒服务器端的小伙伴们返回javascript格式的,可以通过callback传参返回函数名的API哦。另外补充一点,MIME Type中text/html和text/plain的最大区别就是,前者是带格式的html文件,后者返回的只是纯粹的纯文本格式。最后还是那句:本文仅提供作者个人见解,难免错漏,如有问题,还望拍正!

jQuery处理JSONP的更多相关文章

  1. jQuery 调用jsonp实现与原理

    jQuery 调用jsonp实现与原理 您的评价:        收藏该经验     阅读目录 1.客户端代码 2.服务器端 通过jQuery实现JSONP 一般的ajax是不能跨域请求的,因此需要使 ...

  2. jQuery的jsonp跨域是这么回事.

    实现跨域请求的有iframe,img,script中的src属性.那么jquery是如何解决跨域请求的呢? 一:项目jsonp2中有个app.js文件,代码如下: function app(json) ...

  3. jquery ajax jsonp跨域调用实例代码

    今天研究了AJAX使用JSONP进行跨域调用的方法,发现使用GET方式和POST方式都可以进行跨域调用,这里简单分享下,方便需要的朋友 客户端代码 复制代码 代码如下: <%@ Page Lan ...

  4. 基于jQuery的Jsonp跨域[Get方式]

    由于目前的项目需要无刷新的跨域操作数据,整理了下自己使用的基于jQuery的Jsonp跨域[Get方式]. 代码如下: Javascript部分 $(function(){ $.ajax({ asyn ...

  5. jQuery中jsonp函数实现

    由于浏览器中的同源策略,不同的域名,不同的协议,甚至不同的端口都无法请求数据.因此出现了浏览器跨域请求数据问题. Jsonp是解决跨域问题的一个非常流行的方法. JSONP(JSON with Pad ...

  6. C# WebClient、jQuery ajax jsonp实现跨域

    WebClient 无传输数据获取 Uri uri = new Uri(allURL); WebClient wc = new WebClient(); wc.Encoding = System.Te ...

  7. 使用springMVC和Jquery实现JSONP

    JSONP这个东东是啥我就不写了,直接贴实现的代码 JAVA代码: /** * * 查询用户是否已经提交认证获取已经是认证会员 * * 使用spring mvc的直接返回string会遇到分号转义后字 ...

  8. 说说JSON和JSONP,也许你会豁然开朗,含jQuery使用jsonp用例

    [原创]说说JSON和JSONP,也许你会豁然开朗,含jQuery用例  前言: 由于Sencha Touch 2这种开发模式的特性,基本决定了它原生的数据交互行为几乎只能通过AJAX来实现. 当然了 ...

  9. jQuery使用JSONP时的错误处理

    概述 什么是域,简单来说就是协议+域名或地址+端口,3者只要有任何一个不同就表示不在同一个域.跨域,就是在一个域中访问另一个域的数据. 如果只是加载另一个域的内容,而不需要访问其中的数据的话,跨域是很 ...

  10. JQuery Ajax jsonp

    JQuery ajax jsonp $.ajax({ method:"POST", url:"http://localhost:8081/ChenLei/PeopleSe ...

随机推荐

  1. Centos7下安装CUDA

    https://developer.nvidia.com/cuda-80-ga2-download-archive https://developer.nvidia.com/rdp/cudnn-dow ...

  2. [原创]PHP使用Redis实现Session共享

    目录 前言 设计方案 1. 通过php自身session配置实现 2. 设置用户自定义会话存储函数 前言 小型web服务, session数据基本是保存在本地(更多是本地磁盘文件), 但是当部署多台服 ...

  3. 大数据-HBase HA集群搭建

    1.下载对应版本的Hbase,在我们搭建的集群环境中选用的是hbase-1.4.6 将下载完成的hbase压缩包放到对应的目录下,此处我们的目录为/opt/workspace/ 2.对已经有的压缩包进 ...

  4. [BZOJ 5072][Lydsy1710月赛]小A的树

    传送门 \(\color{green}{solution}\) 嗯...其实我也不太会,所以大胆猜个结论吧(后来证了一下,然后放弃了...). 我们发现如果要使一个联通块的黑点数量为\(k\)的方案最 ...

  5. Wi-Fi科普讲稿

    Wi-Fi 从入门到?? 组员:deleted 什么是Wi-Fi Wi-Fi 在中文里又称作"无线热点",是Wi-Fi联盟制造商的商标做为产品的品牌认证,是一个创建于IEEE 80 ...

  6. (转)调优 DB2 UDB v8.1 及其数据库的最佳实践

    原文:https://www.ibm.com/developerworks/cn/data/library/techarticles/dm-0404mcarthur/index.html 简介 性能是 ...

  7. (转)mysql 备份与恢复mysqlhotcopy

    原文:http://fuwenchao.blog.51cto.com/6008712/1331910 mysqlhotcopy是一个Perl脚本,最初由Tim Bunce编写并提供.它使用LOCK T ...

  8. Python爬虫学习:Python内置的爬虫模块urllib库

    urllib库 urllib库是Python中一个最基本的网络请求的库.它可以模拟浏览器的行为发送请求(都是这样),从而获取返回的数据 urllib.request 在Python3的urllib库当 ...

  9. HDU 1102 Constructing Roads(kruskal)

    Constructing Roads There are N villages, which are numbered from 1 to N, and you should build some r ...

  10. Flex4 初始化过慢解决方法

    昨天找了个免费.net空间,想测试一下做的一个简单Flex4 上传项目的效果.上传所有文件到网站之后,访问项目页面,进度条一点一点艰难的向前移动,到了100%后却不出现程序界面,等待一会儿还是没有出现 ...