针对用的比较多的Deferred进行解读,所有注解都在代码行中
(function (jQuery) {
var sliceDeferred = [].slice;
jQuery.extend({
Deferred: function (func) {
var doneList = jQuery.Callbacks("once memory"),//成功回调函数列表
failList = jQuery.Callbacks("once memory"),//失败回调函数列表
progressList = jQuery.Callbacks("memory"),//消息过程回调函数列表
state = "pending",//初始状态 还有 resolved、rejected
lists = {
resolve: doneList,
reject: failList,
notify: progressList
},
//异步队列的只读副本
promise = {
done: doneList.add, //添加到成功回调函数列表的方法
fail: failList.add, //添加到失败回调函数列表的方法
progress: progressList.add,//添加到消息过程回调函数的列表方法
state: function () {
return state;
},
isResolved:doneList.fired,//成功回调函数列表是否被执行
isRejected: failList.fired,//失败回调函数列表是否被执行
then: function (doneCallbacks, failCallbacks, progressCallbacks) {//快速添加到成功、失败、消息回调函数列表方法
deferred.done(doneCallbacks).fail(failCallbacks).progress(progressCallbacks);
return this;
},
always: function () {
deferred.done.apply(deferred, arguments).fail.apply(deferred, arguments);
return this;
},
//工具方法,过滤当前异步队列的状态和参数,并且返回一个新的异步队列副本
//处理ajax中嵌套ajax ,这个简称过滤器
pipe: function (fnDone, fnFail, fnProgress) {
return jQuery.Deferred(function (newDefer) {
jQuery.each({
done: [fnDone, "resolve"],
fail: [fnFail, "reject"],
progress:[fnProgress,"notify"]
}, function (handler,data) {
var fn = data[0],
action = data[1],
returned;
if (jQuery.isFunction(fn)) {
deferred[handler](function () {
returned = fn.apply(this, arguments);
if (returned && jQuery.isFunction(returned.promise)) {
returned.promise().then(newDefer.resolve, newDefer.reject, newDefer.notify);
} else {
newDefer[action + "With"](this === deferred ? newDefer : this, [returned]);
}
});
} else {
deferred[handler](newDefer[action]);
}
});
}).promise();
},
promise: function (obj) {
if (obj == null) {
obj = promise;
} else {
for (var key in promise) {
obj[key] = promise[key];
}
}
return obj;
}
},
//把只读副本promise中的方法添加到异步队列deferred中
deferred = promise.promise({}),//异步队列
key;
//添加触发成功、失败、消息过程回调函数列表的方法
for (key in lists) {
//deferred.resolve=doneList.fire
//deferred.reject=failList.fire
//deferred.notify=progressList.fire
deferred[key] = lists[key].fire;
//deferred.resolveWith=doneList.fireWith
//deferred.rejectWith=failList.fireWith
//deferred.notifyWith=progressList.fireWith
deferred[key + "With"] = lists[key].fireWith;
}
//分别在deferred中追加三个成功回调函数、三个失败函数
deferred.done(function () {
state = "resolved";
}, failList.disable, progressList.lock).fail(function () {
state = "rejected";
}, doneList.disable, progressList.lock);
//如果传递了函数类型的参数,就执行
if (func) {
//如果传入的参数为function,调用参数函数时,指定上下文对象为deferred,参数为deferred
//这样传入的函数可以调用deferred的方法
func.call(deferred, deferred);
}
//全部处理完成
return deferred;
},
//Deferred帮助类 jQuery.when(deferreds)
when: function (firstParam) {
//arguments 其实是一个对象,有点类似数组,这里通过[].slice.call(arguments,0)转换为数组
//但是如果是真实的object={name:'',age:30}这种,[].slice.call(object,0)是行不通的
var args = sliceDeferred.call(arguments, 0),
i = 0,
length = args.length,
pValues = new Array(length),
count = length,
pCount = length,
deferred = length <= 1 && firstParam && jQuery.isFunction(firstParam.promise) ? firstParam : jQuery.Deferred(),
promise = deferred.promise();
function resolveFunc(i){
return function (value) {
args[i] = arguments.length > 1 ? sliceDeferred.call(arguments, 0) : value;
if (!(--count)) {
deferred.resolveWith(deferred, args);
}
};
}
function progressFunc(i) {
return function (value) {
pValues[i] = arguments.length > 1 ? sliceDeferred.call(arguments, 0) : value;
deferred.notifyWith(promise, pValues);
};
}
if (length > 1) {
for (; i < length; i++) {
if (args[i] && args[i].promise && jQuery.isFunction(args[i].promise)) {
args[i].promise().then(resolveFunc(i), deferred.reject, progressFunc(i));
} else {
--count;
}
}
if (!count) {
deferred.resolveWith(deferred, args);
}
} else if (deferred !== firstParam) {
deferred.resolveWith(deferred, length ? [firstParam] : []);
}
return promise;
}
});
})(jQuery)
//对Pipe使用的讲解
//Demo--01
var defer = $.Deferred(),
filtered = defer.pipe(function (value) {
return value * 2;
});
defer.resolve(5);
filtered.done(function (value) {
alert("Value is ( 2*5 = ) 10: " + value);
});
//Demo--02
var defer = $.Deferred(),
filtered = defer.pipe(null, function (value) {
return value * 3;
});
defer.reject(6);
filtered.fail(function (value) {
alert("Value is ( 3*6 = ) 18: " + value);
});
//Demo--03
var request = $.ajax(url, { dataType: "json" }),
chained = request.pipe(function (data) {
return $.ajax(url2, { data: { user: data.userId } });
});
chained.done(function (data) {
//url2返回后的数据
});
//对When的使用方法
//Demo--01
var d1 = $.Deferred();
var d2 = $.Deferred();
var d3 = $.Deferred();
$.when(d1, d2, d3).done(function (v1, v2, v3) {
console.log(v1); // v1 is undefined
console.log(v2); // v2 is "abc"
console.log(v3); // v3 is an array [ 1, 2, 3, 4, 5 ]
});
//Demo--02
$.when($.ajax("/page1"), $.ajax("/page2")).done(function (a1, a2) {
/* a1 and a2 are arguments resolved for the
page1 and page2 ajax requests, respectively */
var jqXHR = a1[2]; /* arguments are [ "success", statusText, jqXHR ] */
if (/Whip It/.test(jqXHR.responseText)) {
console.log("第一个页面的数据");
}
});
//Demo--03 then为快捷的done、fail、progress
$.when($.ajax("test.aspx")).then(function (data, textStatus, jqXHR) {
alert(jqXHR.status);
});