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. Dubbo 自定义异常,你是怎么处理的?

    前言 记录Dubbo对于自定义异常的处理方式. 实现目标 服务层异常,直接向上层抛出,web层统一捕获处理 如果是系统自定义异常,则返回{"code":xxx,"msg& ...

  2. leetcode-54-螺旋矩阵

    题目描述: 给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素. 示例 1: 输入: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7 ...

  3. JavaScript执行环境和作用域(链)的那些事

    执行环境 什么是执行环境 提起作用域,我们不得不说说什么是执行环境.执行环境定义了变量或函数有权访问的其他数据,并决定其各自的行为.每一个执行环境都有一个对应的变量对象,这个对象的作用就是保存在环境中 ...

  4. string容器的简单实现

    1.业务使用main.cpp #include "pch.h" #include <iostream> int main() { mystring s1;//无参构造函 ...

  5. SSAS有几种模式?

    SQL2012中两种,SQL2016好像有三种,下面的第三种好像是2016才有.

  6. 安卓手机移动端Web开发调试之Chrome远程调试(Remote Debugging)

    一.让安卓打debug模式的apk包 二.将电脑中的chrome升级到最新版本,在chrome浏览器地址栏中输入chrome://inspect/#devices: 在智能手机还未普及时,移动设备的调 ...

  7. linux ln 命令,相当于windows快捷方式

    ln -s 源文件 目标文件. ln -s  **  **,它只会在你选定的位置上生成一个文件的镜像,不会占用磁盘空间, 硬链接ln ** **,没有参数-s, 它会在你选定的位置上生成一个和源文件大 ...

  8. LINQ入门教程之各种标准查询操作符(二)

    续上篇LINQ入门教程之各种标准查询操作符(一) LINQ入门教程之各种标准查询操作符(二) 7.  聚合操作符 8.  集合操作符 9.  生成操作符 #region 生成操作符 即从现有序列的值中 ...

  9. (转)DB2下载地址总结

    原文:https://blog.csdn.net/huozengguang/article/details/58602910 DB2 v8.2,v9.1,v9.5,v9.7下载地址 下列都是完全版包含 ...

  10. android开发中的BaseAdapter之理解(引用自网络,总结的很好,谢谢)

    android中的适配器(Adapter)是数据与视图(View)之间的桥梁,用于对要显示的数据进行处理,并通过绑定到组件进行数据的显示. BaseAdapter是Android应用程序中经常用到的基 ...