介绍
什么是deferred对象
deferred对象是一个延时对象,函数延迟到某个点才开始执行,改变执行状态的方法有两个(成功:resolve和失败:reject),分别对应两种执行回调(成功回调函数:done和失败回调函数fail)
var wait = function() {
var der = $.Deferred(); //创建deferred对象
var test = function(){
console.log("111");
der.resolve("222")
}
test()
return der
}
$.when(wait()) //$.when()参数里面必须是deferred对象
.done(function(data){
console.log("执行成功",data)
})
.fail(function(){
console.log("执行失败")
})
//打印结果:
//111
//222 ys
实现
Defferred的实现跟jQuery内部Callbacks函数密不可分 Callbacks源码分析,要用到其内部的fireWith函数,该函数主要用于控制参数传递以及执行list中的所有回调函数。
Deferred: function(func){
//tuples数组储存延迟对象的不同状态信息描述
var tuples = [
["resolve", "done", jQuery.Callbacks("once memory")],
["reject", "fail", jQuery.Callbacks("once memory")]
],
promise = {
then(){
},
promise(obj){
return obj != null ? jQuery.extend(obj, promise) : promise
}
},
//延迟对象
deferred = {}
tuples.forEach((tuple, i)=>{
//创建Callbacks队列函数,list=jQuery.Callbacks("once memory")
var list = tuple[2]
//扩展promise对象,promise[ done | fail ] = list.add
//调用done,fail,progress会给队列里面添加处理函数
promise[tuple[1]] = list.add
//给deferred扩展resolve,reject
// deferred.resolve = function() { deferred.resolveWith(...) }
// deferred.reject = function() { deferred.rejectWith(...) }
deferred[tuple[0]] = function(){
//给fireWith传递参数,指定this
deferred[tuple[0] + "With"](this === deferred ? promise : this , arguments)
return this
}
deferred[tuple[0] + "With"] = list.fireWith
})
//扩展deferred属性,相当于合并promise跟deferred,
//基本数据类型传参是按值传递,不会改变原对象。引用数据类型按对象传递、按对象共享传递,该方法会改变实参deferred
// deferred对象上面包含 resolve | reject | promise | done | fail | rejectWith | resolveWith 这些方法
promise.promise(deferred)
return deferred
}
//接受延迟对象的回调函数,返回的是promise对象
when(deferred){
return deferred.promise()
}
以上基本能实现deferred对象功能,包含resolve()及reject两个处理函数
deferred对象包含的方法包括 resolve | reject | promise | done | fail | rejectWith | resolveWith
when()函数返回promise对象,其包括的方法有 done | fail | promise
当执行deferred对象的resolve()方法,相当于执行了deferred.resolveWith(),也就是Callbacks里面的fireWith函数,执行Callbacks队列函数的所有回调函数。deferred.resolve() -> deferred.resolveWith() -> list.fireWith() -> list.fire()
回调函数添加进入Callbacks队列函数是通过 promis.done(回调函数) 添加,promise[tuple[1]] = list.add, 由于创建Callbacks传入了memory参数,jQuery.Callbacks("once memory"),它会在添加函数的同时执行Callbacks队列函数
var wait = function() {
var der = $.Deferred(); //创建deferred对象
var test = function(){
console.log("111");
der.resolve("222") //执行Callbacks队列函数添加回调函数
}
test()
return der
}
$.when(wait()) //$.when()参数里面必须是deferred对象,返回的是promise对象
.done(function(data){ //向Callbacks队列函数添加回调函数,并执行队列函数
console.log("执行成功",data)
})
.fail(function(){
console.log("执行失败")
})
//打印结果:
//111
//222 ys
以上便基本实现了Deferred对象,当然Deferred本身还不仅仅是这些,Deferrred最复杂深奥的代码在promise.then里面,本文没有分析,有空再深入