jquery源码学习笔记(十六)
Posted 蓝度飞
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jquery源码学习笔记(十六)相关的知识,希望对你有一定的参考价值。
首先,先把 then 的整体结构粘贴过来,这里只是为了定位我们将要分析的 resolve 方法,上次已经分析过 then 的结构和返回值。
这里简单的简述一下 then 的主要用途,延迟函数若有获取数据失败等错误发生时,将直接报错,这将会导致后续函数没法继续执行。
在 then 中,有针对状态的区分,在失败状态中,需要去执行 try catch,抛出异常,并执行 rejectWith 方法,来保证程序的稳定性。
then: function( onFulfilled, onRejected, onProgress ) {
var maxDepth = 0;
function resolve( depth, deferred, handler, special ) {
return function(){
// ...
}
}
return jQuery.Deferred( function( newDefer ) {
} ).promise();
}
接下来,我们来重点看看其中的 resolve 方法。
var maxDepth = 0;
// 构建resovle函数,区分progress、reject、resovle三种状态
// 进行中时,会传入 special=newDefer.notifyWith
function resolve( depth, deferred, handler, special ) {
// 返回值是一个函数
return function() {
// 保存this指向
var that = this,
args = arguments,
// 可能会抛出异常
mightThrow = function() {
var returned, then;
// then的返回值中三次调用传入的depth都为0
// maxDepth 在成功、失败的情况使,会在下面执行 maxDepth++
// 执行过++后,就会跳出mightThrow方法
if ( depth < maxDepth ) {
return;
}
// handler 分别可能是 进行中 成功 失败的回调函数
// 当进行中 成功的回调函数未传时,默认为Identity
// 当失败的回调函数未传时,默认为Thrower
returned = handler.apply( that, args );
// 错误处理:抛出异常
if ( returned === deferred.promise() ) {
throw new TypeError( "Thenable self-resolution" );
}
// 当 returned 存在 且 returned 是对象或方法
// 将 returned.then 赋值给 then
then = returned &&
( typeof returned === "object" ||
typeof returned === "function" ) &&
returned.then;
// then是一个函数
if ( isFunction( then ) ) {
// 只有进行中 special 才会有值
if ( special ) {
then.call(
returned,
resolve( maxDepth, deferred, Identity, special ),
resolve( maxDepth, deferred, Thrower, special )
);
} else { // 成功、失败的情况下 没有传递 special
// 执行过后,以下的 resolve 中的 mightThrow 将会跳出
maxDepth++;
then.call(
returned,
resolve( maxDepth, deferred, Identity, special ),
resolve( maxDepth, deferred, Thrower, special ),
resolve( maxDepth, deferred, Identity,
deferred.notifyWith )
);
}
} else { // 当 then 不是一个方法时
// then 不存在,说明 returned 不是 deferred 对象
if ( handler !== Identity ) {
that = undefined;
args = [ returned ];
}
// 执行 fireWith
( special || deferred.resolveWith )( that, args );
}
},
// special 存在就是 notify 调用
// 直接调用 mightThrow 即可
// 否则可能是 resolved 或 rejected,需要捕获异常
process = special ?
mightThrow :
function() {
try {
mightThrow();
} catch ( e ) {
if ( jQuery.Deferred.exceptionHook ) {
jQuery.Deferred.exceptionHook( e,
process.stackTrace );
}
if ( depth + 1 >= maxDepth ) {
if ( handler !== Thrower ) {
that = undefined;
args = [ e ];
}
deferred.rejectWith( that, args );
}
}
};
// 当depth不为 0,解决一下存在的异常
if ( depth ) {
process();
} else {
if ( jQuery.Deferred.getStackHook ) {
process.stackTrace = jQuery.Deferred.getStackHook();
}
// 异步执行 process
window.setTimeout( process );
}
};
}
由于我目前的能力所限,上述代码最后这块的 getStackHook 没什么了解,之后如果了解了,会再补充进来。
以上是关于jquery源码学习笔记(十六)的主要内容,如果未能解决你的问题,请参考以下文章