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. [总结帖]Web小白的基础恶补帖

    1. jQuery实现按钮点击跳转网页 <script src="js/jquery/jQuery-2.2.0.min.js" type="text/javascr ...

  2. 分析解决Java运行时异常

            1 ,基础知识    http://my.oschina.net/u/140462/blog/421128    JVM运行时内存结构          2 ,相关命令    http ...

  3. mysql常用日期、时间查询

    好记性不如烂笔头 select curdate(); --获取当前日期 select last_day(curdate()); --获取本月最后一天. day); -- 获取本月第一天 ,interv ...

  4. STM32-增量式旋转编码器测量

    Development kit:MDK5.14 IDE:UV4 MCU:STM32F103C8T6 一.增量式旋转编码器 1.简介 编码器(encoder)是将信号(如比特流)或数据进行编制.转换为可 ...

  5. 求幂大法,矩阵快速幂,快速幂模板题--hdu4549

    hdu-4549 求幂大法.矩阵快速幂.快速幂 题目 M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 ...

  6. javascript的简单查询和插入和修改

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...

  7. Mac 10.12常用软件清单

    链接: https://pan.baidu.com/s/1slds1OD 密码: 7m5t 配套教程:http://www.cnblogs.com/EasonJim/tag/mac/ 如果失效了,联系 ...

  8. mono for android读书笔记之硬件编程(转)

    本章将会介绍: 传感器的API 加速器编程,设备的方向,近场检测 网络编程 蓝牙编程 上述的技术的应用场景很多,比如: 1.检测当前的网络是否可用,并提醒用户,检测当前的网络类型,比如Wifi.3G. ...

  9. DB2 Check Pending Script

    转载 http://www.zinox.com/archives/144 Thanks to Max Petrenko of DB2 Toronto Lab for sharing a very us ...

  10. (转载)Java中对List集合内的元素进行顺序、倒序、随机排序的示例代码

    1 import java.util.Collections; 2 import java.util.LinkedList; 3 import java.util.List; 4 5 public c ...