zepto源码研究 - ajax.js(请求过程中的各个事件分析)
简要:ajax请求具有能够触发各类事件的功能,包括:触发全局事件,请求发送前事件,请求开始事件,请求结束事件等等,贯穿整个ajax请求过程,这是非常有用的,我们可以利用这些事件来做一些非常有意思的事情比如:拦截器,权限管理等等,另外$.ajax()貌似会返回一个异步请求对象xhr,这个xhr也是继承了defer的promise对象。这些事件中全局事件是绑定在document上的,局部事件由settings.content指定。(不管怎么说事件都是绑定在dom元素上的,至于事件为什么要与dom关联,可能是为了重用event.js吧,本人在此挖个坑,若有人知道,希望能指点一二)。
闲话少说,直接上代码:
/**
*
* 触发自定义事件
* @param context
* @param eventName
* @param data
* @returns {boolean}
*/
function triggerAndReturn(context, eventName, data) {
var event = $.Event(eventName) //创建Event对象
$(context).trigger(event, data) //触发,这里event参数也可以为字符串,但这里对eventName的校验放到$.Event里面区实现
return !event.isDefaultPrevented() //TODO:返回event.isDefaultPrevented?
} // trigger an Ajax "global" event /**
* 触发ajax的全局事件
* @param settings
* @param context
* @param eventName
* @param data
* @returns {*}
*/
function triggerGlobal(settings, context, eventName, data) {
//settings.global 是否触发ajax的全局事件
if (settings.global) return triggerAndReturn(context || document, eventName, data);
}
triggerGlobal是一个公用函数,在ajaxStart,ajaxStop,ajaxBeforeSend,,ajaxSend,ajaxSuccess,ajaxError,ajaxComplete这些方法中触发全局事件,
除了ajaxStart,和ajaxStop 触发绑定在document上的对应事件外,其他的会触发settings.content绑定的事件。
如果你在settings里不设置global为true,则ajax是不会触发各类事件的。
$.active = /**
* 触发全局 ‘ajaxStart’事件
* @param settings
*/
function ajaxStart(settings) {
//settings.global 传递进来的是否触发全局事件参数
//$.active++ === 0 $.active = 0,此判断才会true
if (settings.global && $.active++ === ) triggerGlobal(settings, null, 'ajaxStart')
}
/**
* 尝试抛出所有请求停止事件,写法和ajaxStart相同
* @param settings
*/
function ajaxStop(settings) {
if (settings.global && !(--$.active)) triggerGlobal(settings, null, 'ajaxStop')
}
ajaxStart:如果允许触发全局事件(settings.global),且当前事件为$内部第一个ajax请求,则执行document所绑定的ajaxStart事件。
$.active++ === 0会先若$.active与0比较,然后自加。
// triggers an extra global event "ajaxBeforeSend" that's like "ajaxSend" but cancelable
//触发全局ajaxBeforeSend事件,如果返回false,则取消此次请求 /**
* 请求前置器, beforeSend ,返回false,取消此次请求
* 或抛出 ajaxBeforeSend 全局事件
* 抛出ajaxSend事件
*
* @param xhr
* @param settings
* @returns {boolean}
*/
function ajaxBeforeSend(xhr, settings) {
var context = settings.context
if (settings.beforeSend.call(context, xhr, settings) === false ||
triggerGlobal(settings, context, 'ajaxBeforeSend', [xhr, settings]) === false)
return false triggerGlobal(settings, context, 'ajaxSend', [xhr, settings])
}
ajaxBeforeSend: 可用于拦截请求,判断并决定请求是否发送。这里定义了2个位置可以处理请求,1:settings.beforeSend 函数,2:settings.context所绑定的
ajaxBeforeSend事件。只要其中有一个function返回false,则终止请求。
/**
* 请求成功调用函数
* @param data
* @param xhr
* @param settings
* @param deferred
*/
function ajaxSuccess(data, xhr, settings, deferred) {
var context = settings.context, status = 'success' //调用success函数
settings.success.call(context, data, status, xhr) //调用所有成功回调函数
if (deferred) deferred.resolveWith(context, [data, status, xhr]) //抛出全局事件 'ajaxSuccess'
triggerGlobal(settings, context, 'ajaxSuccess', [xhr, settings, data]) //请求完成
ajaxComplete(status, xhr, settings)
}
// type: "timeout", "error", "abort", "parsererror"
/**
* 请求失败调用函数
* @param error
* @param type
* @param xhr
* @param settings
* @param deferred
*/
function ajaxError(error, type, xhr, settings, deferred) {
var context = settings.context
settings.error.call(context, xhr, type, error)
if (deferred) deferred.rejectWith(context, [xhr, type, error])
triggerGlobal(settings, context, 'ajaxError', [xhr, settings, error || type])
ajaxComplete(type, xhr, settings);
}
// status: "success", "notmodified", "error", "timeout", "abort", "parsererror"
/**
* 请求完成调用函数
* @param status
* @param xhr
* @param settings
*/
function ajaxComplete(status, xhr, settings) {
var context = settings.context //执行complete
settings.complete.call(context, xhr, status)
triggerGlobal(settings, context, 'ajaxComplete', [xhr, settings]) //尝试抛出所有请求停止事件
ajaxStop(settings)
}
$.ajax({url:'http://192.168.1.189:8080/api/v1/_products/get',data:{name:'zhutao'},method:'POST'})
.then(function(){console.log(arguments);});
Object {}
[Object, "success", Object]
$.ajax({url:'http://192.168.1.189:8080/api/v1/_products/get',data:{name:'zhutao'},method:'POST'})
.then(function(){console.log('SUCCESS',arguments);});
Object {}
SUCCESS [Object, "success", Object]0: Objectcode: 9998entity: nullmessage: "商品不存在"__proto__: Object__defineGetter__: __defineGetter__()__defineSetter__: __defineSetter__()__lookupGetter__: __lookupGetter__()__lookupSetter__: __lookupSetter__()constructor: Object()hasOwnProperty: hasOwnProperty()isPrototypeOf: isPrototypeOf()propertyIsEnumerable: propertyIsEnumerable()toLocaleString: toLocaleString()toString: toString()valueOf: valueOf()get __proto__: get __proto__()set __proto__: set __proto__()1: "success"2: Objectabort: (e)always: ()complete: ()done: ()error: ()fail: ()getAllResponseHeaders: ()getResponseHeader: (e)overrideMimeType: (e)pipe: ()progress: ()arguments: nullcaller: nulllength: 0name: ""prototype: Object__proto__: ()<function scope>promise: (e)arguments: nullcaller: nulllength: 1name: ""prototype: Object__proto__: ()<function scope>readyState: 4responseJSON: ObjectresponseText: "{"code":9998,"message":"商品不存在","entity":null}"setRequestHeader: (e,t)arguments: nullcaller: nulllength: 2name: ""prototype: Object__proto__: ()<function scope>state: ()status: 200statusCode: (e)statusText: "OK"success: ()then: ()__proto__: Objectcallee: ()arguments: nullcaller: nulllength: 0name: ""prototype: Object__proto__: ()<function scope>length: 3Symbol(Symbol.iterator): values()__proto__: Object
$.ajax({url:'/get',data:{name:'zhutao'}}).then(function(){console.log('SUCCESS',arguments);},function(){console.log('error');});
Object {}
GET http://192.168.1.198:8000/get?name=zhutao 404 (Not Found)
error
执行ajax的回调函数有两种,1:$.ajax({.....,success:function(){}}); 2:$.ajax({...}).then(function(){});
settings.success 会先执行,然后执行deffer.resolve();利用$.ajax()返回的promise,我们能很方便的做很多事情。
zepto源码研究 - ajax.js(请求过程中的各个事件分析)的更多相关文章
- zepto源码研究 - ajax.js($.ajax具体流程分析)
简要:$.ajax是zepto发送请求的核心方法,$.get,$.post,$.jsonp都是封装了$.ajax方法.$.ajax将jsonp与异步请求的代码格式统一起来,内部主要是先处理url,数据 ...
- zepto源码研究 - ajax.js($.ajaxJSONP 的分析)
简要:jsonp是一种服务器和客户端信息传递方式,一般是利用script元素赋值src来发起请求.一般凡是带有src属性的元素发起的请求都是可以跨域的. 那么jsonp是如何获取服务器的数据的呢? j ...
- zepto源码研究 - fx_methods.js
简要:依赖fx.js,主要是针对show,hide,fadeIn,fadeOut的封装. 源码如下: // Zepto.js // (c) 2010-2015 Thomas Fuchs // Zept ...
- zepto源码研究 - deferred.js(jquery-deferred.js)
简要:zepto的deferred.js 并不遵守promise/A+ 规范,而在jquery v3.0.0中的defer在一定程度上实现了promise/A+ ,因此本文主要研究jquery v3. ...
- zepto源码研究 - fx.js
简要:zepto 提供了一个基础方法animate来方便我们运用css动画.主要针对transform,animate以及普通属性(例如left,right,height,width等等)的trans ...
- zepto源码研究 - callback.js
简要:$.Callbacks是一个生成回调管家Callback的工厂,Callback提供一系列方法来管理一个回调列表($.Callbacks的一个私有变量list),包括添加回调函数, 删除回调函数 ...
- OpenJDK源码研究笔记(十三):Javac编译过程中的上下文容器(Context)、单例(Singleton)和延迟创建(LazyCreation)3种模式
在阅读Javac源码的过程中,发现一个上下文对象Context. 这个对象用来确保一次编译过程中的用到的类都只有一个实例,即实现我们经常提到的"单例模式". 今天,特意对这个上下文 ...
- zepto源码研究 - zepto.js - 1
简要:网上已经有很多人已经将zepto的源码研究得很细致了,但我还是想写下zepto源码系列,将别人的东西和自己的想法写下来以加深印象也是自娱自乐,文章中可能有许多错误,望有人不吝指出,烦请赐教. 首 ...
- 读Zepto源码之Ajax模块
Ajax 模块也是经常会用到的模块,Ajax 模块中包含了 jsonp 的现实,和 XMLHttpRequest 的封装. 读 Zepto 源码系列文章已经放到了github上,欢迎star: rea ...
随机推荐
- 转: memcpy的用法总结
1.memcpy 函数用于 把资源内存(src所指向的内存区域) 拷贝到目标内存(dest所指向的内存区域):拷贝多少个?有一个size变量控制拷贝的字节数:函数原型:void *memcpy(voi ...
- mysql中lock tables与unlock tables
官网:https://dev.mysql.com/doc/refman/5.0/en/lock-tables.html LOCK TABLES tbl_name [[AS] alias] lock_t ...
- 14.4.2 Change Buffer 延迟写
14.4.2 Change Buffer change buffer 是一个特殊的数据结构 用于cahce 改变的secondary index pages 当被影响的pages 不在buffer p ...
- ehci符合USB2.0,uhci,ohci,
uhci ohci ehci他们都是主机控制器的规格,OHCI主要为非PC系统上以及带有SiShe ALi芯片组的 PC主板上的USB芯片,UHCI大多为Intel和Via主板上的USB控制器 ...
- HBase Compact
Region Compact请求是在Region MemStore Flush之后被触发的: boolean shouldCompact = region.flushcache(); // We ju ...
- 【中国剩余定理】【容斥原理】【快速乘法】【数论】HDU 5768 Lucky7
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5768 题目大意: T组数据,求L~R中满足:1.是7的倍数,2.对n个素数有 %pi!=ai 的数 ...
- C#之VS2010开发Web Service
一:创建web service vs2010软件默认的framework是4.0版本,所以想创建web服务的时候压根看不到web服务应用程序.网上有人说vs2010的web service 跟wcf合 ...
- ArcGis : unable to save as template this document is already based on another template
原文:http://forums.esri.com/Thread.asp?c=93&f=989&t=289930 ----------------- I ran into this p ...
- Jmeter安装设置
Linux: 其实下载之后就可以用,不过为了能在命令行直接敲入”jmeter"就可以调出Jmeter程序,还需要进行如下设置. 1. Download apache-jmeter-2.12. ...
- iOS内存管理(一)
最近有时间,正好把iOS相关的基础知识好好的梳理了一下,记录一下内存相关方面的知识. 在理解内存管理之前我觉得先对堆区和栈区有一定的了解是非常有必要的. 栈区:就是由编译器自动管理内存分配,释放过程的 ...