json jsonp 类型

  "json":  把响应的结果当作 JSON 执行,并返回一个JavaScript对象。如果指定的是json,响应结果作为一个对象,在传递给成功处理函数之前使用jQuery.parseJSON进行解析。 解析后的JSON对象可以通过该jqXHR对象的responseJSON属性获得的。json的处理只要是在ajaxConvert方法中把结果给转换成需要是json格式,这是后面的内容,这里主要研究下jsonp的预处理。

  "jsonp": JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。

  跨域这个问题的产生根本原因是浏览器的同源策略限制,理解同源策略的限制同源策略是指阻止代码获得或者更改从另一个域名下获得的文件或者信息。也就是说我们的请求地址必须和当前网站的地指相同。同源策略通过隔离来实现对资源的保护。这个策略的历史非常悠久从Netscape Navigator 2.0时代就开始了。

  解决这个限制的一个相对简单的办法就是在服务器端发送请求,服务器充当一个到达第三方资源的代理中继。虽然是用广泛但是这个方法却不够灵活。

  另一个办法就是使用框架(frames),将第三方站点的资源包含进来,但是包含进来的资源同样要受到同源策略的限制。

  有一个很巧妙的办法就是在页面中使用动态代码元素,代码的源指向服务地址并在自己的代码中加载数据。当这些代码加载执行的时候,同源策略就不会起到限制。但是如果代码试图下载文件的时候执行还是会失败,幸运的是,我们可以使用JSON(JavaScript Object Notation)来改进这个应用

  

a. JSONP的客户端具体实现


  先看一个简单的例子

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script>
alert(jQuery)
</script>
</head>
<body>
</body>
</html>

  通过script是src加载远程的jQuery毫无疑问是可以正常运行的,所以不难发现Web页面上调用js文件时则不受是否跨域的影响

  当然不仅如此,我们还发现凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>等。

  在进一步我们换成契约式接口

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript">
function remoteLoad(data){
alert(data) //远程数据
}
</script>
</head>
<body>
</body>
</html> //在http://code.jquery.com/jquery-1.11.1.min.js 文件中执行(在文档ready之后)
remoteLoad('加载的数据')

  显而易见是可行的,通过加载远程的脚本到本地中执行,很好的绕开了跨域的问题了,但是这样的请求是有问题的,接口是契约式的?

  怎么让远程js知道它应该调用的本地函数叫什么名字呢?毕竟是jsonp的服务者都要面对很多服务对象,而这些服务对象各自的本地函数都不相同啊?我们接着往下看。

  更进一步增加动态回调

<!DOCTYPE html>
<html>
<head>
  <script type="text/javascript">
    var remoteLoad= function(data){};
    var url = "http://code.jquery.com/jquery-1.11.1.min.js?code=1111&callback=remoteLoad";
    var script = document.createElement('script');
    script.setAttribute('src', url);
    document.getElementsByTagName('head')[0].appendChild(script);
</script>
</head>
<body>
</body>
</html>

  不再直接把远程js文件写死,而是编码实现动态查询,而这也正是jsonp客户端实现的核心部分,我们看到调用的url中传递了一个callback参数则告诉服务器,我的本地回调函数叫做remoteLoad,所以请把查询结果传入这个函数中进行调用。

b. jQuery的处理


  在jQuery的ajax中jsonp和jsonpCallback分别对应指定“callback”和“remoteLoad”这两个值。

  jsonp的默认值为“callback”,jsonpCallback的默认值是一个时间戳字段(jQuery.expando + "_" + ( ajax_nonce++ ))比如“jQuery19107833043907303363_1444871956399”。

  我们也可以指定他们,比如{jsonp:”chuaCallBack”,jsonpCallBack:”chuaRemote”}那么在传递的时候url就变成了"http://code.jquery.com/jquery-1.11.1.min.js?..&chuaCallBack=chuaRemote"。

  所以总结其实json的一个核心点:允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

$.ajax({
url : "remoteLoad.js",
dataType : "jsonp",
jsonp : "callback", //传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback : "Handler", //自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
success: function(data) {
console.log(arguments)
}
});

  基本原理OK了,我们看看上面jQuery的使用没有什么太大的区别。

  jQuery其实也大同小异,jQuery的区别最大的不同的就自动帮你生成回调函数并把数据取出来供success属性方法来调用,不是传递的一个回调句柄。

  jQuery实现jsonp的源码处理步骤如下。

  首先,我们需要设置回调函数名称,可以自己定义也可以让jQuery自动设置。

//获取回调函数名称(这个名称可以在ajax的jsonpCallback选项上设置,
//否则通过jQuery默认的方式jsonpCallback()来设置)
//这个回调函数名称是用来告诉后台需要将返回数据包裹到该函数中,返回前端后执行
callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
s.jsonpCallback() :
s.jsonpCallback;

  然后,将回调插入到url或者data选项中(一般来说是URL

if ( jsonProp ) {
s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
} else if ( s.jsonp !== false ) {
s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
}

  再然后,安装回调

//安装回调
overwritten = window[ callbackName ];
window[ callbackName ] = function() {
responseContainer = arguments;
};

  很明显,本来后台应该执行overwritten这个回调的,但是现在换成了执行后面重写的这个回调,那么在jsonp请求完成后就会执行这个重写方法,给responseContainer赋值了。别急overwritten后面有调用到。

  最后,添加延时对象的always响应执行overwritten。

//清除函数(转换完成后执行)
jqXHR.always(function() {
//保存先前存的值
window[ callbackName ] = overwritten; //将jsonpCallback设置回原始值
if ( s[ callbackName ] ) {
//确保重新使用jsonpCallback选项没有杂质
s.jsonpCallback = originalSettings.jsonpCallback; //将callbackName压入oldCallbacks以备将来使用
oldCallbacks.push( callbackName );
} //在请求响应后,如果jsonpCallback指定的回调是一个函数则调用它
if ( responseContainer && jQuery.isFunction( overwritten ) ) {
overwritten( responseContainer[ 0 ] );
} responseContainer = overwritten = undefined;
});

  所以overwritten是在这里面执行的,前面源码中重载过的那个回调在后台调用后获取到了responseContainer值也被用到了。可见我们在设置的jsonpCallback选项指定的回调名(例如chuaRemote)对应的回调先被保存到overwritten中,而这个原始的chuaRemote被赋值为function() {  responseContainer = arguments;};

  在响应处理中chuaRemote会被调用让responseContainer获取到响应值。最后会执行到jqXHR.always添加的函数处理。将chuaRemote恢复到原来的函数overwritten,并执行overwritten(jsonpCallback指定的回调)。主要是always这个监听处理中还清除callbackName指定的函数,以及添加回到历史等等处理。

  

  好了jsonp就分析到这里了,欢迎拍砖。

  如果觉得本文不错,请点击右下方【推荐】!

jQuery-1.9.1源码分析系列(十六)ajax——jsonp原理的更多相关文章

  1. Spring Ioc源码分析系列--@Autowired注解的实现原理

    Spring Ioc源码分析系列--@Autowired注解的实现原理 前言 前面系列文章分析了一把Spring Ioc的源码,是不是云里雾里,感觉并没有跟实际开发搭上半毛钱关系?看了一遍下来,对我的 ...

  2. ABP源码分析二十六:核心框架中的一些其他功能

    本文是ABP核心项目源码分析的最后一篇,介绍一些前面遗漏的功能 AbpSession AbpSession: 目前这个和CLR的Session没有什么直接的联系.当然可以自定义的去实现IAbpSess ...

  3. ABP源码分析三十六:ABP.Web.Api

    这里的内容和ABP 动态webapi没有关系.除了动态webapi,ABP必然是支持使用传统的webApi.ABP.Web.Api模块中实现了一些同意的基础功能,以方便我们创建和使用asp.net w ...

  4. ABP源码分析四十六:ABP ZERO中的Ldap模块

    通过AD作为用户认证的数据源.整个管理用户认证逻辑就在LdapAuthenticationSource类中实现. LdapSettingProvider:定义LDAP的setting和提供Defaut ...

  5. Android源码分析(十六)----adb shell 命令进行OTA升级

    一: 进入shell命令界面 adb shell 二:创建目录/cache/recovery mkdir /cache/recovery 如果系统中已有此目录,则会提示已存在. 三: 修改文件夹权限 ...

  6. spark 源码分析之十六 -- Spark内存存储剖析

    上篇spark 源码分析之十五 -- Spark内存管理剖析 讲解了Spark的内存管理机制,主要是MemoryManager的内容.跟Spark的内存管理机制最密切相关的就是内存存储,本篇文章主要介 ...

  7. jQuery-1.9.1源码分析系列(六) 延时对象应用——jQuery.ready

    还记不记得jQuery初始化函数jQuery.fn.init中有这样是一个分支 //document ready简便写法$(function(){…}) } else if ( jQuery.isFu ...

  8. Vue.js 源码分析(二十六) 高级应用 作用域插槽 详解

    普通的插槽里面的数据是在父组件里定义的,而作用域插槽里的数据是在子组件定义的. 有时候作用域插槽很有用,比如使用Element-ui表格自定义模板时就用到了作用域插槽,Element-ui定义了每个单 ...

  9. jQuery-1.9.1源码分析系列(六) 延时对象续——辅助函数jQuery.when

    $.when的说明 描述: 提供一种方法来执行一个或多个对象的回调函数,返回这些对象的延时(Deferred)对象. 说明(结合实例和源码): 如果你不传递任何参数,  jQuery.when()将返 ...

  10. jQuery-1.9.1源码分析系列(六) 延时对象

    首先我们需要明白延时对象有什么用? 第一个作用,解决时序以及动态添加执行函数的问题. function a(){alert(1)}; function b(){alert(2)}; function ...

随机推荐

  1. win7安装时,避免产生100m系统保留分区的办法

    在通过光盘或者U盘安装Win7操作系统时,在对新硬盘进行分区时,会自动产生100m的系统保留分区.对于有洁癖的人来说,这个不可见又删不掉的分区是个苦恼.下面介绍通过diskpart消灭保留分区的办法: ...

  2. 【原创分享·微信支付】C# MVC 微信支付教程系列之现金红包

            微信支付教程系列之现金红包           最近最弄这个微信支付的功能,然后扫码.公众号支付,这些都做了,闲着无聊,就看了看微信支付的其他功能,发现还有一个叫“现金红包”的玩意,想 ...

  3. C#文件安全管理解析

    在实际的项目开发中,我们经常需要使用到文件的I/O操作,主要包含对文件的增改删查等操作,这些基本的操作我们都是很熟悉,但是较少的人去考虑文件的安全和操作的管理等方面,例如文件的访问权限管理,文件数据的 ...

  4. fir.im Weekly - 关于 iOS10 适配、开发、推送的一切

    "小程序"来了,微信变成名副其实的 Web OS,新一轮的Web App 与Native App争论四起.程序员对新技术永远保持灵敏的嗅觉和旺盛的好奇心,@李锦发整理了微信小程序资 ...

  5. Register-SPWorkflowService 404

    最近需要做一个SharePoint 2013工作流演示环境. 于是在自己的本子上安装了一个虚拟机. 虚拟机操作系统是Windows Server 2012 R2,计划把AD.SQL Server 20 ...

  6. 【从零开始学BPM,Day3】自定义表单开发

    [课程主题] 主题:5天,一起从零开始学习BPM [课程形式] 1.为期5天的短任务学习 2.每天观看一个视频,视频学习时间自由安排. [第三天课程] 1.课程概要 Step 1 软件下载:H3 BP ...

  7. 在树莓派Raspbian下安装支持Hard Float的.NET环境

    [题外话] 最近入了个树莓派玩,系统装的官方推荐的Hard Float的Raspbian,由于衍生自Debian,所以Mono什么的非常好装.但是官方源中的Mono在Hard Float的Raspbi ...

  8. 【初码干货】在Window Server 2016中使用Web Deploy方式发布.NET Web应用的重新梳理

    在学习和工作的过程中,发现很多同事.朋友,在做.NET Web应用发布的时候,依然在走 生成-复制到服务器 这样的方式,稍微高级一点的,就是先发布到本地,再上传到服务器 这种方式不仅效率低下,而且不易 ...

  9. Windows平台分布式架构实践 - 负载均衡(下)

    概述 我们在上一篇Windows平台分布式架构实践 - 负载均衡中讨论了Windows平台下通过NLB(Network Load Balancer) 来实现网站的负载均衡,并且通过压力测试演示了它的效 ...

  10. 分享一个CQRS/ES架构中基于写文件的EventStore的设计思路

    最近打算用C#实现一个基于文件的EventStore. 什么是EventStore 关于什么是EventStore,如果还不清楚的朋友可以去了解下CQRS/Event Sourcing这种架构,我博客 ...