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. SpringBoot整合MyBatis及Thymeleaf

    http://www.cnblogs.com/ludashi/archive/2017/05/08/6669133.html 上篇博客我们聊了<JavaEE开发之SpringBoot工程的创建. ...

  2. 1059 C语言竞赛 (20 分)

    #include <iostream> #include <iomanip> #include <cmath> using namespace std; <& ...

  3. python学习,day4:生成器

    1.生成器:只有在调用是才会生成相应的数据.(比较省内存,它只保留当时生成的.而列表会保存整个列表) a = [i*2 for i in range(10)] #列表生成式 print(a) 这样会把 ...

  4. Java NIO学习与记录(一):初识NIO

    初识 工作中有些地方用到了netty,netty是一个NIO框架,对于NIO却不是那么熟悉,这个系列的文章是我在学习NIO时的一个记录,也期待自己可以更好的掌握NIO. 一.NIO是什么? 非阻塞式I ...

  5. centos 6.6 设备 xxx 似乎不存在, 初始化操作将被延迟

    2019-04-02 问题描述: centos 6.6开启虚拟机之后,网卡服务不能正常启动,报错信息为:设备 xxx(网卡名称)似乎不存在, 初始化操作将被延迟 解决办法: 清空70-persiste ...

  6. Android中9-Patch图片之理解

    在android中,不仅可以将扩展名为.png,.jpg,.gif的普通图片作为图片资源,而且可以将扩展名为.9.png的9-Patch图片作为图片资源.扩展名为.png,.jpg,.gif的普通图片 ...

  7. 再学C/C++ 之 指针常量 和 常量指针

    (1)指针常量,将指针的指向当成常量.即指针变量的值只能在定义的时候初始化,定义后不能修改,也就是说不能改变指针变量的指向.但是不影响所指对象的访问特征.其定义形式为: 类型 * const 指针 / ...

  8. 【es6】js原生的promise

    JavaScript 是单线程的,这意味着任何两句代码都不能同时运行,它们得一个接一个来.在浏览器中,JavaScript 和其他任务共享一个线程,不同的浏览器略有差异,但大体上这些和 JavaScr ...

  9. IDEA 及 Gradle 使用总结

    自动编译组件 目前Android开发的主流开发工具是 Eclipse 和 IDEA 目前主流的自动化打包工具时 ant,maven,gradle. maven工具中有自己的依赖仓库维护,很多开源支持包 ...

  10. 【开源组件】FastDFS极速入门与安装

    FastDFS是一个开源的轻量级的分布式文件系统,为互联网量身定制,充分考虑了冗余备份.负载均衡.线性扩容等机制,并注重高可用.高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供 ...